如何grep和匹配第一次出现的一行?

时间:2016-06-26 17:08:07

标签: shell grep

鉴于以下内容:

title="Bar=1; Fizz=2; Foo_Bar=3;"

我想匹配第一次出现的Bar1。另外,我不想依赖于单词的探测(如前面的双引号),因为模式可能位于行的中间。

这是我的尝试:

$ grep -o -m1 'Bar=[ ./0-9a-zA-Z_-]\+' input.txt
Bar=1
Bar=3

我使用-m / --max-count,假设在num匹配后停止读取文件,但它不起作用。为什么这个选项不能按预期工作?

我可以与head -n1混合使用,但我想知道是否可以通过grep实现这一目标?

4 个答案:

答案 0 :(得分:2)

grep line -oriented,因此在使用-m [1] <时,显然会根据计算匹配项/ SUP>   - 即使在线上找到多个匹配项(并且使用-o单独输出)。

虽然我不知道单独使用grep来解决问题(除了 GNU grep&#39; -P选项 - 请参阅anubhava's helpful answer),awk可以这样做(以便携式方式):

$ awk -F'Bar=|;' '{ print $2 }' <<<"Bar=1; Fizz=2; Foo_Bar=3;"
1

如果应包含字段名称,请使用print "Bar=" $2 另请注意,通过stdin提供输入的<<<方法(所谓的here-string)特定于Bash,Ksh,Zsh;如果必须遵守POSIX,请改用echo "..." | grep ...

[1]选项-m-o 不是 grep POSIX spec.的一部分,但GNU和BSD / OSX grep都支持它们并已选择实现基于行的逻辑 这与标准 -c选项一致,该选项计算&#34;选定的行&#34;,即匹配的行的数量
grep -o -c 'Bar=[ ./0-9a-zA-Z_-]\+' <<<"Bar=1; Fizz=2; Foo_Bar=3;"会产生 1 。 功能

答案 1 :(得分:2)

gnu grep中使用基于perl的正则表达式风格,您可以使用:

grep -oP '^(.(?!Bar=\d+))*Bar=\d+' <<< "Bar=1; Fizz=2; Foo_Bar=3;"
Bar=1

(.(?!Bar=\d+))*将匹配0个或更多不具有Bar=\d+模式的字符,从而确保我们首先匹配Bar=\d+

如果意图是在=之后打印值,则使用:

grep -oP '^(.(?!Bar=\d+))*Bar=\K\d+' <<< "Bar=1; Fizz=2; Foo_Bar=3;"
1

答案 2 :(得分:1)

您可以使用grep -P(假设您使用的是gnu grep)并使用正面预测((?=.*Bar))来实现grep:

echo "Bar=1; Fizz=2; Foo_Bar=3;" | grep -oP -m 1 'Bar=[ ./0-9a-zA-Z_-]+(?=.*Bar)'

答案 3 :(得分:1)

首先使用grep使行以Bar开头,然后在行的开头获取Bar:

grep -o "Bar=.*" input.txt | grep -o -m1 "^Bar=[ ./0-9a-zA-Z_-]\+"

如果您有大文件,可以使用

进行优化
grep -o -m1 "Bar=.*" input.txt | grep -o -m1 "^Bar=[ ./0-9a-zA-Z_-]\+"