Советы по Perl сценарий регулярного выражения - PullRequest
1 голос
/ 16 мая 2019

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

У меня есть файл с двумя столбцами - в первом столбце находятся номера библиотеки Дьюи, а во втором столбце - штрих-коды.Число Дьюи должно быть примерно 150 ADD или 150.40 ADD.Я ищу строки, в которых отсутствуют 3-х символьные инициалы автора.Мой пример файла выглядит так:

100.20 SAD 350694345
250 ADD 369803434
300 360349320
300.1534234 ZOO 353000303
210 3633400340

Я написал скрипт для вывода всех строк, в которых нет инициалов автора после числа Дьюи.Регулярное выражение ищет 3 цифры перед необязательной точкой, затем ноль или более необязательных цифр, затем пробел, а затем 3 буквы инициалов автора.

$filename = 'call.txt';
$output = 'result.txt';
open(FILE, $filename) or die 'Could not open $filename';
foreach $line (<FILE>) {
if ($line !~ /^\d{3}\.*\d* [a-zA-Z]{3}/) {

open (CALL, '>', $output) or die $!;
print CALL $line;
}
}

Когда я запускаю скрипт, он выводит только5-я строка

210 3633400340

Я не уверен, почему она также не получает строку 3, поскольку она не соответствует регулярному выражению?На выходе должны быть все числа Дьюи без инициалов автора.Итак, желаемый результат:

300 360349320
210 3633400340

Я был бы очень признателен за некоторую помощь с этим

спасибо J

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

Проблемы:

  • Вы должны ВСЕГДА использовать use strict; use warnings qw( all );.(Поскольку он всегда должен использоваться, мы не будем показывать его в наших фрагментах.) Это бесплатно обнаруживает многочисленные проблемы.
  • Вам не нужно использовать глобальные переменные.(use strict; поможет вам в этом, за исключением файловых дескрипторов.)
  • Повторно создавая файл в цикле, вы забиваете все, кроме последней строки вывода.(Это проблема, о которой вы спрашивали.)
  • Ваш шаблон неправильно считает последовательности из более чем трех символов, как если бы они были последовательностями из трех символов.
  • При использовании <> в контексте списка, вы загружаете весь файл в память, когда его было бы так же просто прочитать из файла строка за строкой.
  • Ваши сообщения об ошибках не очень полезны.

Исправлено:

#!/usr/bin/perl

use strict;
use warnings qw( all );

my $in_qfn  = 'call.txt';
my $out_qfn = 'result.txt';

open(my $fh_in, '<', $in_qfn)
   or die("Can't open \"$in_qfn\": $!\n");
open(my $fh_out, '>', $out_qfn)
   or die("Can't create \"$out_qfn\": $!\n");

while (<$fh_in>) {
   print $out_fh $_ if !/^\S+\s+\S{3}\s/;
}

Программа гораздо полезнее, если вы не пишете имена файлов жестко.

#!/usr/bin/perl

use strict;
use warnings qw( all );

while (<>) {
   print if !/^\S+\s+\S{3}\s/;
}

Использование:

script call.txt >result.txt

или

script <call.txt >result.txt
0 голосов
/ 16 мая 2019

Вы открываете файл с усечением (">") каждый раз, когда находите совпадение.Переместите открытый (CALL, ...) перед циклом for.

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