有没有一种复杂的方法来grep这个文件

is there a sophisticated way to grep this file

我有一个文件。用 BNF 写的可能是

 <line>:== ((<ISBN10>|<ISBN13>)([a-Z/0-9]*))  {1,4})

例如

   123456789X/abscd/1234567890123/djfkldsfjj

如何在每行中仅检索一个 ISBN10 或 ISBN13,即使该行中有更多 ISBN。如果行中有更多 ISBN,则应该只取行中的第一个。

当我这样 grep 时

     grep -Po "[0-9]{9,13}X{0,1}" file 

然后我得到的行数比文件原来的行数多。 (因为最多可以有 4 个 ISBN)

我还需要文件的行数应该是 grepresult 的行数。

有什么建议吗?

一个简单的解决方案是在正则表达式中包含行的开头:

grep -Po "^[0-9]{9,13}X{0,1}" file

这确保了第一个之后的匹配不满足正则表达式。从您的 BNF 看来,ISBN(如果存在)肯定是该行的第一个字符。

另一种方法是使用 sed:

 sed -n "s/\([0-9]\{9,13\}X\).*//p" file

这与您的模式以及该行的其余部分相匹配,但只打印您的模式。然后您可以使用另一个实用程序来添加行号。例如。将您的输出通过管道传输到 nl -nrz -w9.

好吧,假设提供的其他答案不正确,假设 'first' ISBN 不在行首,您总是可以在 perl 中尝试。

#!/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 很像 grep 做的。所以你可以用类似于 grep 的方式调用它:

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;'