递归grep仅匹配特定行号

递归grep仅匹配特定行号

如何找到包含特定模式的文件在特定行号上?假设我有一个目录,其中包含一堆包含 3 行的文本文件,例如:

Title A
Category X
Description Y

如何 grep/过滤每个在线Category X文件2?如何找到包含Title Aas 行的文件1

我查看了 grep 手册页、ripgrep 和替代方案,但不确定是否可以将模式搜索限制为特定行号。

答案1

你可以awk这样使用:

awk 'FNR == 2 && /Category X/ {print FILENAME}' *

答案2

当在第二行中找到模式时,您可以使用findwithawk来退出处理文件的其余部分,或者如果在第二行中没有找到模式,也可以退出。

find -type f -name 'xyz*.txt' -exec \
    awk 'NR==2{ if(/pattern/) print FILENANE; exit }' {} \;

答案3

grep只是为了好玩:

PAT="Category X"
LN=2
> grep -n "$PAT" file* | grep ":$LN:$PAT$" | grep -o "^[^:]*"
file1
file2

答案4

GNU grep 可用于您的用例:

$ grep -Plzr '^(?:.*\n){1}.*Category X' .

grep通常在每行的基础上工作,但 GNU grep 添加了一个-z选项,它将整个文件视为一行,因为它分隔在文本文件中找不到的字符 ( \0) 上的记录。

现在我们可以将正则表达式应用于整个文件。您的要求是仅搜索第二行,因此我们不做任何事情就驶过一行^(?:.*\n){1}

插入符号 ^ 将正则表达式锚定为从头开始。该点不能跨行,因为它与换行符不匹配。

然后.*Category X将开始查找下一行,即第二行,但不会跨行,因此如果在第二行找到模式则匹配。

如果存在匹配,该-l选项会将文件名列出到 STDOUT。

-r选项将使 grep 递归运行(GNU 功能)。

-P能够编写 Perl 风格的正则表达式(GNU 功能)。


这是使用 GNU find+sed 组合解决该问题的另一个方法:

$ find . -type f -exec sed -ns '2{/Category X/F;}' {} +

GNU find + GNU xargs 输入 Perl 也可以做到这一点:

find . -type f ! -size 0 -print0 |
xargs -r0 perl -lne '
  (eof||$.==2)&&do{
    print $ARGV if $.==2 && /Category X/;
    close  ARGV; undef $.;
  };
'

相关内容