鉴于以下内容:
title="Bar=1; Fizz=2; Foo_Bar=3;"
我想匹配第一次出现的Bar
值1
。另外,我不想依赖于单词的探测(如前面的双引号),因为模式可能位于行的中间。
这是我的尝试:
$ grep -o -m1 'Bar=[ ./0-9a-zA-Z_-]\+' input.txt
Bar=1
Bar=3
我使用-m
/ --max-count
,假设在num匹配后停止读取文件,但它不起作用。为什么这个选项不能按预期工作?
我可以与head -n1
混合使用,但我想知道是否可以通过grep
实现这一目标?
答案 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_-]\+"