Grep 并仅返回匹配列
Grep and returning only column of match
如果我想从具有不同列数的文件中进行搜索,如下所示:
ppl:apple age:5 F add:blabla love:dog
ppl:tom M add:blablaa love:cat
ppl:jay age:3 M love:apple
ppl:jenny acc:jen age:8 F add:blabla
...
文件是制表符分隔的,我想要的输出是:
age:5
age:3
age:8
...
使用 grep age:
将 return 整行,而
使用 cut -f2
将 return 一些不需要的列:
age:5
M
age:3
acc:jen
而且 cut -f2|grep age:
和 grep age|cut -f2:
都不起作用
我的数据可能在 11-23 列之间,
有没有更简单的方法使用 grep sed 或 awk 来处理它,
非常感谢
您可以使用以下脚本:
cat file|grep age|awk '{for(i=1;i<22;i++){if($i ~ /^age:/)print $i}}'
可能是最好的选择。
适用于 GNU sed
和 BSD/OSX 的解决方案 sed
:
sed -nE 's/^.*[[:blank:]](age:[0-9]+).*$//p' file
使用 GNU sed
你可以简化为:
sed -nr 's/^.*\t(age:[0-9]+).*$//p' file
两个命令都匹配整个输入行,如果它包含感兴趣的age:
字段,则将其替换为捕获的字段(</code>),并打印结果;其他行将被忽略。</p>
<hr>
<p>原始答案,在澄清要求之前:</p>
<p>假设在 <code>age:
存在 的行上,它始终是 2nd 制表符分隔字段,awk
是最好的解决方案:
awk ' ~ /^age:/ { print }' file
~ /^age:/
仅匹配第二个空格分隔字段以文字 age:
开头的行
{ print }
只是打印该字段。
你也可以使用 sed
sed -nr 's/^.*(age:.).*$//p' input_pattern.txt
其中 input_pattern.txt 包含您的数据。
将正则表达式搜索限制在第 11 至 23 列:
awk '{ for(i = 11; i <= 23; i++) { if ($i ~ /^age:/) print $i } }' file
grep
本身可以通过使用 -o
/--only-matching
开关来完成此操作,无需其他工具。你应该能够做到:
grep -o '\<age:[0-9]\+'
解释正则表达式中不太常见的部分:
\<
是一个零宽度的断言,你在一个单词的开头(也就是说,age 前面有一个非单词字符或出现在行的开头,但它是实际上不匹配那个非单词字符);这会阻止你匹配,比如 image:123
。它在技术上不需要空格,所以它会匹配 :age:
或类似的东西;如果这是一个问题,请匹配 \t
本身并使用 cut
或 tr
稍后将其删除。
\+
表示"match 1 or more occurrences of the preceding character class"(也就是[0-9]
,所以匹配一位或多位数字)。 \+
相当于重复 class 两次,第二个副本后跟 *
,例如[0-9][0-9]*
,除了更短,一些正则表达式引擎可以更好地优化 \+
。
如果我想从具有不同列数的文件中进行搜索,如下所示:
ppl:apple age:5 F add:blabla love:dog
ppl:tom M add:blablaa love:cat
ppl:jay age:3 M love:apple
ppl:jenny acc:jen age:8 F add:blabla
...
文件是制表符分隔的,我想要的输出是:
age:5
age:3
age:8
...
使用 grep age:
将 return 整行,而
使用 cut -f2
将 return 一些不需要的列:
age:5
M
age:3
acc:jen
而且 cut -f2|grep age:
和 grep age|cut -f2:
都不起作用
我的数据可能在 11-23 列之间, 有没有更简单的方法使用 grep sed 或 awk 来处理它, 非常感谢
您可以使用以下脚本:
cat file|grep age|awk '{for(i=1;i<22;i++){if($i ~ /^age:/)print $i}}'
适用于 GNU sed
和 BSD/OSX 的解决方案 sed
:
sed -nE 's/^.*[[:blank:]](age:[0-9]+).*$//p' file
使用 GNU sed
你可以简化为:
sed -nr 's/^.*\t(age:[0-9]+).*$//p' file
两个命令都匹配整个输入行,如果它包含感兴趣的age:
字段,则将其替换为捕获的字段(</code>),并打印结果;其他行将被忽略。</p>
<hr>
<p>原始答案,在澄清要求之前:</p>
<p>假设在 <code>age:
存在 的行上,它始终是 2nd 制表符分隔字段,awk
是最好的解决方案:
awk ' ~ /^age:/ { print }' file
~ /^age:/
仅匹配第二个空格分隔字段以文字age:
开头的行
{ print }
只是打印该字段。
你也可以使用 sed
sed -nr 's/^.*(age:.).*$//p' input_pattern.txt
其中 input_pattern.txt 包含您的数据。
将正则表达式搜索限制在第 11 至 23 列:
awk '{ for(i = 11; i <= 23; i++) { if ($i ~ /^age:/) print $i } }' file
grep
本身可以通过使用 -o
/--only-matching
开关来完成此操作,无需其他工具。你应该能够做到:
grep -o '\<age:[0-9]\+'
解释正则表达式中不太常见的部分:
\<
是一个零宽度的断言,你在一个单词的开头(也就是说,age 前面有一个非单词字符或出现在行的开头,但它是实际上不匹配那个非单词字符);这会阻止你匹配,比如image:123
。它在技术上不需要空格,所以它会匹配:age:
或类似的东西;如果这是一个问题,请匹配\t
本身并使用cut
或tr
稍后将其删除。\+
表示"match 1 or more occurrences of the preceding character class"(也就是[0-9]
,所以匹配一位或多位数字)。\+
相当于重复 class 两次,第二个副本后跟*
,例如[0-9][0-9]*
,除了更短,一些正则表达式引擎可以更好地优化\+
。