Допустим, у меня есть это:
something,"another thing"
Это можно легко разделить с помощью обычной функции разделения.
Теперь я хочу иметь более сложный синтаксис, и я делаю:
something,"in a string, oooh",rgba(4,2,0)
Это не работает с обычной функцией разделения.
Я пытался использовать такие вещи, как замена запятых внутри определенных типов токенов, но это стало слишком сложным, и я чувствую, что должен быть лучший способ.
Затем я попробовал использовать регулярные выражения, которые работали, пока мне не пришлось добавить новую функцию, которая не работала бы с моим регулярным выражением (что было довольно плохо), также совпадения регулярных выражений могут быть медленными, и это должно быть как как можно быстрее.
Что было бы лучшим способом решить эту проблему?
Вот исходный репозиторий для дополнительного контекста https://github.com/hyprland-community/hyprparse И рассматриваемый формат - это формат конфигурации hyprland.
Да! Именно так!
Вы можете попробовать генератор парсеров (см. lib.rs/parsing список). Я использовал combine
и был им доволен, но я не уверен, что он самый используемый.
Можете ли вы опубликовать полный формат, который вы хотели бы распознать? Всегда ли это три вещи подряд, где первая — это символы, за которыми следует что-то в кавычках, а затем — значение цвета? Или есть еще вещи, которые следует учитывать? Также: какое регулярное выражение вы использовали?
Кроме того, вы контролируете формат? Потому что если это так, то то, что у вас есть, очень близко к CSV. Если вы просто решите сделать это CSV (поместив поле rgba в кавычки), вы можете просто использовать парсер CSV.
@phimuemue, если это просто двойные кавычки и запятые, и вы не хотите использовать csv по какой-либо причине, также довольно легко выполнить разделение.
К сожалению, я не контролирую формат, это формат, используемый hyprland, вот текущий источник github.com/hyprland-community/hyprparse и используемое регулярное выражение (?P<token>.+deg|rgba?\(.*?\)|".*?"|[^,]*)(?:,?|$)
Перебрать строку, сохраняя состояние контекста:
Внутри контекста запятая не имеет значения разделителя.
Ограничения: Это полуночный взлом!
Смотрите также 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:?}");
}
Для вашего второго примера я предполагаю, что вы хотите получить
something
,"in a string, oooh"
иrgba(4,2,0)
. Это верно?