#perl
#perl
Вопрос:
У меня есть анализатор файлов perl, который я пытаюсь переписать. Это динамический анализатор, и мне нужно извлечь значение из строки, разделенной запятыми.
Строка, из которой я хочу получить одно значение, выглядит примерно так:
ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16
(Это единственная строка в каждом анализируемом файле, которая начинается с. ENTRYNAME-
Все после -
изменений для каждого анализируемого файла)
Я хочу значение после второй запятой. ( 99955
в примере выше)
Я попробовал следующее, но безуспешно:
if (/ ENTRYNAME-((.*),(.*),(.*))/ )
{
$entry_nr = $3;
print "entry number = $entry_nr";
next;
}
Комментарии:
1. Предпочтительно использовать
Text::CSV
или , по крайней мере, разделить линию на разделителе,split /,/
2. Будут ли эти строки csv когда-либо заключаться в кавычки и иметь встроенные ‘,’ в строке?
Ответ №1:
Проблема в том, что ваша первая строка захвата .*
является жадной, поэтому она будет использовать всю вашу строку. Затем он вернется назад, чтобы найти две запятые и, как результат, совпадение с конца.
Также:
(
По какой-то странной причине вы сопоставляете литеральные круглые скобки. Поскольку у вас их нет, они никогда не будут совпадать.- Вам не нужно экранировать запятые
,
- В вашем регулярном выражении не может быть случайного пробела
/ ENTRY...
, если он не указан в целевой строке - Вам не нужно захватывать строки, которые вы не собираетесь использовать
Простое решение — использовать более строгую группу захвата (включая пункты выше):
if (/ENTRYNAME-d ,d ,(d )/ )
Это приведет к захвату $1
.
Как указывает mpapec в комментарии, вы можете использовать Text::CSV
для анализа данных CSV. Это будет намного безопаснее. Если ваши данные достаточно просты, это решение подойдет.
Комментарии:
1. Спасибо! Это, наконец, свело все воедино. Я бы использовал Text::CSV, но входные данные никоим образом не просты.
2. @user2837756 Вы, вероятно, должны использовать, только
Text::CSV
если у вас есть правильные данные csv. Регулярное выражение является жизнеспособным мелкомасштабным решением для ограниченного набора данных с ограниченными вариациями. Но вам, вероятно, следует добавить некоторые безопасные средства защиты и сообщения об ошибках на случай, если вы столкнетесь с неожиданными изменениями.
Ответ №2:
разделите его на массив и адресуйте напрямую:
my @a = split /,/, $_;
print $a[2];
что здесь происходит, так это то, что все, что находится в $_ (обычно из for (@allmylines) {
цикла), будет разделяться при каждом появлении ,
, помещая их все в array ( @a
) и удаляя ,
. затем вы можете обращаться к полям в массивах, начиная с 0 для первого поля. таким образом, если вы хотите обратиться к третьему полю, используйте $a[2]
для извлечения третьего элемента.
Комментарии:
1. @Brett_Schneider Что, если в каждой строке есть строки в кавычках со встроенными запятыми?
2. @octopusgrabbus в вопросе ничего этого не говорится, поэтому я не вижу смысла тратить время на его обдумывание.
3. @Victor я рассмотрел это и, таким образом, расширил свой ответ до этого момента.
Ответ №3:
По возможности отделяйте синтаксический анализ от обработки и проверки ваших данных.
В этом случае, если у вас есть значения, разделенные запятыми, продолжайте и разделите эти значения. Тогда позаботьтесь о фильтрации ваших данных. Используете ли вы Text::CSV
для синтаксического анализа, это отдельная проблема, хотя, вероятно, это хорошая идея.
use strict;
use warnings;
while (<DATA>) {
chomp;
my @cols = split ',';
if ($cols[0] =~ /^ENTRYNAME/) {
print $cols[2], "n";
}
}
__DATA__
ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16
Выводит:
99955