Справка по регулярным выражениям Perl (анализ столбца) - PullRequest
1 голос
/ 26 марта 2011

Я застрял здесь. Не уверен, почему мой рег экс не будет работать. У меня есть текстовый файл с разделителями трубы с серией столбцов. Мне нужно извлечь 3-й столбец.

Файл:

A|B|C|D|E|F|G|H|I
2011-03-03 00:00:00.0|1|60510271|254735|27751|BBB|1|-0.1619023623|-0.009865904
2011-03-03 00:00:00.0|1|60510270|254735|27751|B|3|-0.0064786612|-0.0063739185
2011-03-03 00:00:00.0|1|60510269|254735|27751|B|3|-0.0084998226|-0.009244384

Регулярное выражение:

$> head foo | perl -pi -e 's/^(.*)\|(.*)\|(.*)\|(.*)$/$3/g'

выход

-0.1619023623
-0.0064786612
-0.0084998226

Очевидно, что выводится не тот столбец.

Мысли?

Ответы [ 6 ]

4 голосов
/ 26 марта 2011

Обычно проще / проще (KISS) НЕ использовать регулярные выражения для форматов файлов со структурированными разделителями. Просто разбейте строку на «|» разделитель и получить 3-е поле.

awk -F"|" '{print $3}' file

с рубином (1,9 +)

ruby -F"\|" -ane 'puts $F[2]' file

С Perl, он похож на вышеупомянутый Ruby однострочный.

perl -F"\|" -ane 'print $F[2]."\n"' file
1 голос
/ 26 марта 2011

Первой мыслью было Text :: CSV (упомянутое Мэттом Б), но если данные выглядят как пример, я бы сказал, что split - правильный выбор.

Не проверено:

$> head foo | perl -le 'while (<>) { print (split m{|})[2]; }'

Если вы действительно хотите регулярное выражение, я бы использовал что-то вроде этого:

s{^ [^\|]* \| [^\|]* \| ([^\|]*) \| .*$}{$1}gx;
1 голос
/ 26 марта 2011

Вы должны сделать свой шаблон жадным - так:

's/^(.*?)\|(.*?)\|(.*?)\|(.*)$/$3/g'

1 голос
/ 26 марта 2011

Как насчет использования реального парсера вместо того, чтобы взламывать регулярные выражения?Text::CSV должны выполнить работу.

my $csv = Text::CSV->new({sep_char => "|"});
1 голос
/ 26 марта 2011

.* будет по умолчанию соответствовать столько, сколько может, поэтому ваш RE выбирает последний три столбца (и все, что было до), а не первый три (и все после). Вы можете избежать этого (по крайней мере) двумя способами: (1) вместо .* ищите [^|]* или (2) сделайте ваши операторы повторения нежадными: .*? вместо .*.

(Или вы можете явно разделить строку вместо того, чтобы сопоставить все это с одним RE. Возможно, вы захотите попробовать оба подхода и посмотреть, какой из них работает лучше, если это имеет значение. Разделение, вероятно, даст более длинный, но более четкий код.)

0 голосов
/ 02 декабря 2015
(?<=\|)\d{8}

Возможно, это сработает (?<=\|) положительный взгляд на символ |, за которым следуют 8 цифр

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...