从man grep
:
-o, --only-matching
Print only the matched (non‐empty) parts of a matching line, with each such part on a separate output line.
一个简单的问题:如何仅打印匹配行中匹配的(非空)部分,每个部分都在一个相同的输出线?
答案1
以下是使用 Perl 单行代码完成此工作的方法:
~/dev/perl$ cat file1
blah foo blah bar blah foo
blah bar blah bar
bar blah bar foo foo blah bar foo
~/dev/perl$ perl -ane '@l=$_=~/(foo)/g;print"@l\n"if@l' file1
foo foo
foo foo foo
~/dev/perl$
解释:
perl -ane ' # invoque Perl interpreter
@l=$_=~/(foo)/g; # match all "foo" (here insert the string to match) on a line and store in an array (@l)
print"@l\n"if@l # print the array if not empty
'
file1 # file to be processed
答案2
使用 grep 和 awk 的另一种可能的解决方案:
└─$ cat file1
blah foo blah bar blah foo
blah bar blah bar
bar blah bar foo foo blah bar foo
─$ grep -on foo file | awk -F ":" 's != $1 || NR==1{s=$1;if(p){print p};p=$2;next};{p=p" "$2;}END{print p}'
foo foo
foo foo foo
即:
grep -在 foo 文件上--> 匹配模式 foo,并在输出的每一行前加上输入文件中以 1 为基数的行号。如果匹配多个,则重复相同的行号,例如:
└─$ grep -on foo file
1:foo
1:foo
3:foo
3:foo
3:foo
awk:
-F ":"
--> 考虑冒号作为分隔符来解析字段s != $1 || NR==1
--> 检查变量是否s
与第一个字段的值不同,或者正在分析的行是否是第一行。如果为真,则执行以下操作:s=$1;
--> 变量 s 取第一个字段的值(行号)if(p){print p};
--> 如果变量p
有值,则打印它p=$2;
--> 变量p
采用第二个字段的值(匹配模式)next
--> 进入下一次迭代,并s != $1 || NR==1
在下一行开始重新评估条件
{p=p" "$2;}
--> 如果步骤 2 中的条件为假(当行号与前一行相同时:同一行上有多个匹配),则变量p
将自身的值连接到所分析行的第二个字段(匹配模式)(它们之间有一个空格)。END{print p}
--> 最后,当所有行都分析完毕后,打印变量 p 中保存的最后一个值。
因此,在上述情况下:
1 号线-->1:foo
分析:条件为真,因为NR==1
。s
取值1
,p
未取值因此不打印,p 取值 foo,继续分析第二行。
2号线-->1:foo
分析:条件为假,因为 s==$1(此行的第一个字段为 = 1,变量s
来自1
上一步)且 NR==2(我们在第二行)。因此我们继续执行{p=p" "$2;}
,变量p
取其自身值 + " " + $2(即foo
),变成foo foo
3号线-->3:foo
分析:条件为真,因为s!=$1
(确实s
是1
,第三行的第一个字段是 3)。s
取值3
,p
被赋值(foo foo
来自上一步),因此打印,p
取值foo
,继续分析第 4 行
4号线-->3:foo
分析:条件为假,因为 s==$1(此行的第一个字段为 = 3,变量s
来自3
上一步)且 NR==4(我们在第 4 行)。因此我们继续执行{p=p" "$2;}
,变量p
取其自身值 + " " + $2(即foo
),变成foo foo
5号线-->3:foo
被分析:条件为假,因为 s==$1(此行的第一个字段为 = 3,变量s
来自3
步骤 3)且 NR==5(我们在第 5 行)。因此我们继续执行{p=p" "$2;}
,变量p
取其自身值(即上一步中的 'foo foo')+“”+$2(即foo
),变成foo foo foo
结尾--> 没有更多行需要分析。因此,END
执行 之后的部分,并打印{print p}
变量p
(现在包含上一步中的 )。foo foo foo
最终输出:
foo foo
foo foo foo