我有一个文件。用BNF写成
<line>:== ((<ISBN10>|<ISBN13>)([a-Z/0-9]*)) {1,4})
例如
123456789X/abscd/1234567890123/djfkldsfjj
即使在行中有更多的ISBN,我如何才能将ISBN10或ISBN13抓住。如果行中有更多的ISBN,则只需排在第一个。
当我以这种方式抓住时
grep -Po "[0-9]{9,13}X{0,1}" file
然后,我得到的线比最初的文件还要多。(因为在线可能有最大4个ISBN)
我还需要文件的linecount是grepresult的linecount。
有什么建议?
好吧,假设提供的另一个答案是假设'第一个'ISBN不在行开始时不正确的,那么您可以随时尝试。
#!/usr/bin/perl
use strict;
use warnings;
while (<>) {
chomp;
my ( $first_isbn, @rest ) = m/(d{9,13}X{0,1})/g;
print $., ":", $first_isbn, "n" if $first_isbn;
}
$.
是perl中的行号,因此,如果有匹配项,我们将其打印和匹配。 <>
像格雷普一样,读取并迭代文件名或stdin。因此,您可以以类似的方式调用此内容:
perl myscript.pl <filename>
或:
cat <filename> | ./myscript.pl
这将单线形式为:
perl -lne 'my ( $first_isbn ) = m/(d{9,13}X{0,1})/g; print $., ":", $first_isbn, "n" if $first_isbn;'
一个微不足道的解决方案是将行的开始包括在您的正则:
中grep -Po "^[0-9]{9,13}X{0,1}" file
这可以确保第一个之后与之匹配的匹配不满意。似乎是从您的BNF来看,如果存在的ISBN可以保证是该行的第一个字符。
另一种方法是使用sed:
sed -n "s/([0-9]{9,13}X).*/1/p" file
这与您的图案与线路的其余部分匹配,但只能打印出您的图案。然后,您可以使用另一个实用程序添加行号。例如。将输出输出到nl -nrz -w9
。