How to grep for contents after pattern?

例如,给定一个文件:

potato: 1234
apple: 5678
potato: 5432
grape: 4567
banana: 5432
sushi: 56789

我希望获取以 potato:开始的所有行,但只管道跟随 potato:的数字。所以在上面的例子中,输出是:

1234
5432

我该怎么做?

193371 次浏览
grep 'potato:' file.txt | sed 's/^.*: //'

grep 查找包含字符串 potato:的任何行,然后,对于这些行中的每一行,sed用空字符串(s/...//-用第二部分替换第一部分,第二部分为空)替换(s///-替换)任何字符(.*) ,从行的开始(^)一直到序列 :的最后一次出现(冒号后跟空格)。

或者

grep 'potato:' file.txt | cut -d\   -f2

For each line that contains potato:, cut will split the line into multiple fields delimited by space (-d\ - d = delimiter, \ = escaped space character, something like -d" " would have also worked) and print the second field of each such line (-f2).

或者

grep 'potato:' file.txt | awk '{print $2}'

对于包含 potato:的每一行,awk将打印默认用空格分隔的第二个字段(print $2)。

或者

grep 'potato:' file.txt | perl -e 'for(<>){s/^.*: //;print}'

包含 potato:的所有行都被发送到一个内联(-e) Perl脚本,该脚本从 stdin获取所有行,然后,对于这些行中的每一行,执行与上面第一个示例中相同的替换操作,然后打印它。

或者

awk '{if(/potato:/) print $2}' < file.txt

The file is sent via stdin (< file.txt sends the contents of the file via stdin to the command on the left) to an awk script that, for each line that contains potato: (if(/potato:/) returns true if the regular expression /potato:/ matches the current line), prints the second field, as described above.

或者

perl -e 'for(<>){/potato:/ && s/^.*: // && print}' < file.txt

该文件通过 stdin(< file.txt,见上文)发送给一个与上文类似的 Perl 脚本,但是这一次它也确保每一行包含字符串 potato:(/potato:/是一个正则表达式,如果当前行包含 potato:,则匹配它,如果匹配(&&) ,则继续应用上文描述的正则表达式并打印结果)。

sed -n 's/^potato:[[:space:]]*//p' file.txt

可以将 Grep 看作受限制的 Sed,或者将 Sed 看作广义的 Grep。在这种情况下,Sed 是一个很好的轻量级工具,可以做您想做的事情——当然,还有其他一些合理的方法。

或者使用正则表达式断言: grep -oP '(?<=potato: ).*' file.txt

这将在每次比赛后打印所有内容,只在同一行上:

perl -lne 'print $1 if /^potato:\s*(.*)/' file.txt

这将做同样的事情,除了它也将打印所有后续行:

perl -lne 'if ($found){print} elsif (/^potato:\s*(.*)/){print $1; $found++}' file.txt

使用以下命令行选项:

  • -n在输入文件的每一行上循环
  • -l在处理之前删除新行,然后再将它们添加回来
  • 执行 perl 代码

您可以使用 grep,如其他答案所述。但是您不需要 grep、 awk、 sed、 perl、 cut 或任何外部工具。你可以用纯 bash。

试试这个(分号可以让你把它们放在一行中) :

$ while read line;
do
if [[ "${line%%:\ *}" == "potato" ]];
then
echo ${line##*:\ };
fi;
done< file.txt

# # 告诉 bash 从前面删除 $line 中“ :”最长的匹配项。

$ while read line; do echo ${line##*:\ }; done< file.txt
1234
5678
5432
4567
5432
56789

或者,如果您想要的是键而不是值,%% 会告诉 bash 从 $line 的末尾删除最长的“ :”匹配项。

$ while read line; do echo ${line%%:\ *}; done< file.txt
potato
apple
potato
grape
banana
sushi

要分割的子字符串是“ :”,因为空格字符必须用反斜杠转义。

你可以在 Linux文档计划找到更多这样的。

grep -Po 'potato:\s\K.*' file

-P使用 Perl 正则表达式

-o只输出匹配

\spotato:之后的空间匹配

\K省略匹配

.*匹配字符串的其余部分

现代 BASH 支持正则表达式:

while read -r line; do
if [[ $line =~ ^potato:\ ([0-9]+) ]]; then
echo "${BASH_REMATCH[1]}"
fi
done
grep potato file | grep -o "[0-9].*"