Соответствие шаблону с отбрасыванием символов новой строки

Как извлечь значения из CSV-подобной строки, отбрасывая символы новой строки (\r\n или \n) с шаблоном.

Строка выглядит так:

1.1;2.2;Example, 3

Обратите внимание, что есть только 3 значения и разделитель ;. Проблема, с которой я столкнулся, состоит в том, чтобы придумать шаблон, который считывает значения при удалении символов новой строки (файл поступает с компьютера с Windows, поэтому он имеет \r\n, читает его из Linux и хотел бы быть независимым от используемого символа новой строки).

Мой простой пример прямо сейчас:

s = "1.1;2.2;Example, 3\r\n";
p = "(.-);(.-);(.-)";
a, b, c = string.match(s, p);
print(c:byte(1, -1));

Два последних символа, напечатанные вышеприведенным кодом, — это \r\n.

Проблема в том, что оба, \r и \n, обнаруживаются классами %c и %s (управляющие символы и символы пробела), как показано в этом коде:

s = "a\r";
print(s:match("%c"));
print(s:match("%s"));
print(s:match("%d"));

Итак, можно ли исключить из совпадения символы новой строки? (Не следует предполагать, что последние два символа будут символами новой строки)

Значение 3º может содержать пробелы, знаки препинания и буквенно-цифровые символы, а поскольку \r\n определяются как пробелы, шаблон типа `"(.-);(.-);([%w%s%c]-).*" не работай.


person Javier Mr    schedule 15.07.2014    source источник


Ответы (2)


Ваш шаблон

p = "(.-);(.-);(.-)";

не работает: третье поле всегда пустое, потому что .- совпадает как можно меньше. Вам нужно привязать его к концу строки, но тогда третье поле будет содержать конечные символы новой строки:

p = "(.-);(.-);(.-)$";

Итак, просто остановитесь на первом завершающем символе новой строки. Это также закрепляет последнее совпадение. Вместо этого попробуйте этот шаблон:

p = "(.-);(.-);(.-)[\r\n]";

Если конечные символы новой строки необязательны, попробуйте этот шаблон:

p = "(.-);(.-);(.-)[\r\n]*$";

person lhf    schedule 15.07.2014
comment
Да, я перепутал схему. Основываясь на вашем шаблоне, я изменил его на `p = (.-);(.-);(.-)%c*$; так что это также работает, если нет нового символа строки. Спасибо. - person Javier Mr; 15.07.2014

Без какого-либо опыта lua я нашел наивное решение:

clean_CR = s:gsub("\r","");
clean_NL = clean_CR:gsub("\n","");

С синтаксисом регулярных выражений POSIX я бы использовал

^([^;]*);([^;]*);([^\n\r]*).*$

.. с "\n" и "\r", возможно, включенными как "^M", "^@" (символы управления/юникода) .. в зависимости от вашего редактора.

person flowtron    schedule 15.07.2014
comment
Если вы пойдете по этому пути, проще сделать s=s:gsub("[\r\n]+",""). - person lhf; 15.07.2014
comment
думал, что будет более короткий путь, я просто не знаю lua - проголосовал за ваш комментарий за добавленную стоимость! - person flowtron; 18.07.2014