普通版 sed/grep

普通版 sed/grep

我有一个文件,需要计算文件中输入字符串的所有部分匹配项。
我将向您展示我需要的一个简单的示例:

在包含以下内容的文件中:

Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat

我需要计算部分字符串“Good -*-Cat”(其中 * 可以是任何数字,无所谓)出现的次数。预期输出次数为 2。

任何帮助将不胜感激。

答案1

鉴于

$ cat file
Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat

然后

$ grep -c 'Good-.*-Cat' file
2

请注意,这是一个匹配行数- 例如,它不适用于每行多次出现的情况,或者跨越多行出现的情况。

或者,使用awk

awk '/Good-.*-Cat/ {n++} END {print n}' file

如果您需要每行匹配多个可能的出现情况,那么我建议perl

perl -lne '$c += () = /Good-.*?-Cat/g }{ print $c' file

匹配/Good-.*?-Cat/g多次g)和非贪婪*(.*?)并且() =赋值强制在标量上下文中评估匹配,以便我们可以将它们添加到计数中。

或者,您可以grep在 perl 兼容正则表达式(PCRE)模式中使用(以启用非贪婪修饰符),-o仅输出匹配的部分 - 然后计算以下部分wc

grep -Po 'Good-.*?-Cat' file | wc -l

perl如果您还需要匹配可能跨越行边界的出现,那么您可以通过取消设置记录分隔符(注意:这意味着整个文件被吸入内存)并添加正则表达式修饰符来实现s,例如

perl -0777 -nE '$c += () = /Good-.*?-Cat/gs }{ say $c' file

答案2

awk,多次出现,以空格分隔

$ awk '{for(i=1;i<=NF;i++ ) count+=match($i,/Good-.*-Cat/)};END{print count}' input.txt
4
$ cat input.txt
Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog Good-Whatever-Cat Good-Something-Cat
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat

sed + wc,非多次出现

这使用负模式匹配//!d删除,只留下感兴趣的行。

$ sed '/Good-.*-Cat/!d' input.txt
Good-Black-Cat
Good-Golden-Dog Good-Whatever-Cat
Good-Tabby-Cat
$ sed '/Good-.*-Cat/!d' input.txt | wc -l
3

壳解决方案,非多次出现

case...esac这里是结合文件读取循环的shell 方式:

$ n=0; while IFS= read -r line || [ -n "$line" ]; do case "$line" in "Good-"*"-Cat") n=$((n+1));; esac; done < input.txt; echo "$n"
2

或者使用指示

n=0
while IFS= read -r line || [ -n "$line" ]; do 
    case "$line" in 
        "Good-"*"-Cat") n=$((n+1));; 
    esac
done < input.txt
echo "$n"

解释:

  • n=0初始化n计数器变量
  • while IFS= read -r line || [ -n "$line" ]; do...done < input.txt是 shell 脚本中使用的标准文件读取循环,具有|| [ -n "$line" ]保护功能,可以处理可能不以换行符结尾的文件
  • case "$line" in "Good-"*"-Cat") n=$((n+1));; esac对所需字符串进行模式匹配,并使用$((...))算术扩展来增加计数器变量。

答案3

普通版 sed/grep

sed 's/\(Good-[^ ]*-Cat\)/XXXX\n/g' input.txt | grep -c XXXX

虽然XXXX可以是文件中未出现的任何模式。此方法将所有匹配项替换为模式XXXX和换行符,以便通过基本的 grep 表达式轻松计数。

顺便说一句,如果你从字面上理解“其中 * 可以是任何东西”,至少据我理解,任何此类程序的输出始终为 0 或 1,因此我假设它至少不应包含空格。

相关内容