bash 查找以字符串开头的行

Jér*_*mie 11 grep bash sed string

我有一堆文件,我想找到哪个包含以某个字符串开头的连续行。

例如对于以下文件:

Aaaaaaaaaaaa
Baaaaaaaaaaa
Cxxxxxxxxx
Cyyyyyyyyy
Czzzzzzzzz
Abbbbbbbbbbb
Bbbbbbbbbbbb
Caaaaaa
Accccccccccc
Bccccccccccc
Cdddddd
Ceeeeee
Run Code Online (Sandbox Code Playgroud)

有不止一行以“C”开头,所以我希望通过命令找到这个文件。
例如对于以下文件:

Aaaaaaaaaaaa
Baaaaaaaaaaa
Cxxxxxxxxx
Abbbbbbbbbbb
Bbbbbbbbbbbb
Caaaaaa
Accccccccccc
Bccccccccccc
Cdddddd
Run Code Online (Sandbox Code Playgroud)

总是有一行以“C”开头,我不想要这个文件。我想过使用 agrep或 ased但我不知道该怎么做。也许使用正则表达式^C.*$^C或类似的东西。任何的想法 ?

Sté*_*las 6

pcregrep

pcregrep -rMl '^C.*\nC' .
Run Code Online (Sandbox Code Playgroud)

POSIXly:

find . -type f -exec awk '
  FNR==1 {last=0; printed=0; next}
  printed {next}
  /^C/ {if (last) {print FILENAME; printed=1; nextfile} else last=1; next}
  {last=0}' {} +
Run Code Online (Sandbox Code Playgroud)

(尽管这意味着使用awk不支持的实现完全读取所有文件nextfile)。


GNU 版本grep高达 2.5.4:

grep -rlP '^C.*\nC' .
Run Code Online (Sandbox Code Playgroud)

似乎工作,但它是偶然的,它不能保证工作。

在 2.6 修复之前(通过这次提交),GNUgrep忽略了它使用的 pcre 搜索函数会匹配当前由 处理的整个缓冲区grep,从而导致各种令人惊讶的行为。例如:

grep -P 'a\s*b'
Run Code Online (Sandbox Code Playgroud)

将匹配包含以下内容的文件:

bla
bla
Run Code Online (Sandbox Code Playgroud)

这将匹配:

printf '1\n2\n' | grep -P '1\n2'
Run Code Online (Sandbox Code Playgroud)

但是这个:

(printf '1\n'; sleep 1; printf '2\n') | grep -P '1\n2'
Run Code Online (Sandbox Code Playgroud)

或者:

(yes | head -c 32766; printf '1\n2\n') > file; grep -P '1\n2' file
Run Code Online (Sandbox Code Playgroud)

不会(因为1\n2\n跨两个由 处理的缓冲区grep)。

不过,这种行为最终被记录在案:

15- 如何跨行匹配?

标准 grep 不能这样做,因为它基本上是基于行的。因此,仅使用 '[:space:]' 字符类不会以您期望的方式匹配换行符。但是,如果您的 grep 是在启用 Perl 模式的情况下编译的,则可以使用 Perl 's' 修饰符(使 '.' 匹配换行符):

     printf 'foo\nbar\n' | grep -P '(?s)foo.*?bar'
Run Code Online (Sandbox Code Playgroud)

在2.6修复后,文档没有修改(我曾经在那里报告过)。