Разделить строку запятыми, но запятые в токене

Допустим, у меня есть это:

something,"another thing"

Это можно легко разделить с помощью обычной функции разделения.

Теперь я хочу иметь более сложный синтаксис, и я делаю:

something,"in a string, oooh",rgba(4,2,0)

Это не работает с обычной функцией разделения.

Я пытался использовать такие вещи, как замена запятых внутри определенных типов токенов, но это стало слишком сложным, и я чувствую, что должен быть лучший способ.

Затем я попробовал использовать регулярные выражения, которые работали, пока мне не пришлось добавить новую функцию, которая не работала бы с моим регулярным выражением (что было довольно плохо), также совпадения регулярных выражений могут быть медленными, и это должно быть как как можно быстрее.

Что было бы лучшим способом решить эту проблему?

Вот исходный репозиторий для дополнительного контекста https://github.com/hyprland-community/hyprparse И рассматриваемый формат - это формат конфигурации hyprland.

Для вашего второго примера я предполагаю, что вы хотите получить something, "in a string, oooh" и rgba(4,2,0). Это верно?

phimuemue 09.02.2023 11:18

Да! Именно так!

Yavor 09.02.2023 11:20

Вы можете попробовать генератор парсеров (см. lib.rs/parsing список). Я использовал combine и был им доволен, но я не уверен, что он самый используемый.

phimuemue 09.02.2023 11:23

Можете ли вы опубликовать полный формат, который вы хотели бы распознать? Всегда ли это три вещи подряд, где первая — это символы, за которыми следует что-то в кавычках, а затем — значение цвета? Или есть еще вещи, которые следует учитывать? Также: какое регулярное выражение вы использовали?

phimuemue 09.02.2023 11:25

Кроме того, вы контролируете формат? Потому что если это так, то то, что у вас есть, очень близко к CSV. Если вы просто решите сделать это CSV (поместив поле rgba в кавычки), вы можете просто использовать парсер CSV.

BurntSushi5 09.02.2023 12:08

@phimuemue, если это просто двойные кавычки и запятые, и вы не хотите использовать csv по какой-либо причине, также довольно легко выполнить разделение.

Masklinn 09.02.2023 12:26

К сожалению, я не контролирую формат, это формат, используемый hyprland, вот текущий источник github.com/hyprland-community/hyprparse и используемое регулярное выражение (?P<token>.+deg|rgba?\(.*?\)|".*?"|[^,]*)(?:,?|$)

Yavor 09.02.2023 22:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
111
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Перебрать строку, сохраняя состояние контекста:

  1. Никто
  2. Внутри "..."
  3. Внутри (...)

Внутри контекста запятая не имеет значения разделителя.

Ограничения: Это полуночный взлом!

Смотрите также Rust Playground

fn split(s: String) -> Vec<String> {
    let mut context = None;
    let mut i = 0;
    let mut start = 0;
    let mut items = Vec::new();
    
    for c in s.chars() {
        if context == Some('"') {
            if c == '"' {
                context = None;
            }
            i = i+1;
            continue;
        } else if context == Some('(') {
            if c == ')' {
                context = None;
            }
            i = i+1;
            continue;
        }
        
        if c == '"' || c == '(' {
            context = Some(c);
        }
        
        if c == ',' && context.is_none() {
            items.push(s[start..i].to_string());
            start = i + 1;
        }
        
        i = i+1;
    }
    items.push(s[start..i].to_string());
    items
}


fn main() {
    let s = "something,\"in a string, oooh\",rgba(4,2,0)".to_string();
    println!("{:?}", split(s));
    // -> ["something", "\"in a string, oooh\"", "rgba(4,2,0)"]
}

Спасибо всем за помощь, в конце концов я придумал свое собственное решение с помощью людей, которых я знал в реальной жизни, вот мое решение:

fn previous_rgb(index: usize, chars: Vec<char>) -> bool {
    let string: String = chars[index-3..index].iter().collect();
    let string = string.as_str();
    if string == "gba" || string == "rgb" {
        true
    } else {
        false
    }
}

fn splitter<Str: ToString>(s: Str) -> Vec<String> {
    let mut is_in_rgb = false;
    let mut is_in_str = false;
    let mut last = 0;
    let chars: Vec<_> = s.to_string().chars().collect();
    let mut final_str = vec![];
    for (index, c) in chars.iter().enumerate() {
        if *c == '(' && previous_rgb(index, chars.clone()) && !is_in_str {
            is_in_rgb = true;
        } else if *c == ')' && is_in_rgb && !is_in_str {
            is_in_rgb = false;
        } else if *c == '"' && is_in_str {
            is_in_str = false;
        } else if *c == '"' && !is_in_str {
            is_in_str = true;
        } else if *c == ',' && !is_in_str && !is_in_rgb {
            final_str.push(chars[last..index].iter().collect());
            last = index + 1
        };
    }
    final_str.push(chars[last..].iter().collect());
    final_str
}

fn main() {
    let splitted = splitter(r#"test,test: rgba(5,4,3),"test2, seperated""#);
    println!("{splitted:?}");
}

Другие вопросы по теме

Похожие вопросы

Синтаксический анализ текста python для разделения списка на куски, включая предшествующие разделители
Средство форматирования ввода не допускает значение, когда оно должно
Удалите все строки между двумя строками с определенными шаблонами с помощью однострочного Perl и регулярных выражений
Перейти к регулярным выражениям или кешированию — что быстрее в долгосрочной перспективе?
Добавьте логическое значение функции года и замените трехбуквенный месяц на его номер месяца в массиве строк
Сопоставление шаблонов регулярных выражений с использованием аннотации @Pattern в Spring Boot
Выполнять несколько операций регулярных выражений в каждой строке текстового файла и сохранять извлеченные данные в соответствующем столбце
Как проверить, принадлежит ли дата, указанная в виде строки, к интервалу из 2 дат, указанных в другой строке?
Замаскируйте любой 15-значный или 16-значный номер кредитной карты в строке, заменив на X, кроме последних 4 цифр. Сложная головоломка с регулярными выражениями в C#
Сопоставьте "MALE", но не "FEMALE" в SQL