使用 grep/linux/bash 计算重复字符串的重叠出现次数

Count overlapping occurences of a repeated string using grep/linux/bash

我正在尝试计算重复字符串的出现次数。例如

echo 'joebobtomtomtomjoebobmike' | grep -o 'tomtom' | wc -l

这输出 1,但显然字符串 'tomtom' 适合这里两次。我怎样才能让它计算两次?

谢谢!

您可以使用这个 awk 脚本

{
    count = 0
    [=10=] = tolower([=10=])
    while (length() > 0) {
        m = match([=10=], pattern)
        if (m == 0)
             break
        count++
        [=10=] = substr([=10=], m + 1)
    }
    print count
}

说明

我们首先将行转换为全部小写以忽略大小写。该脚本通过在匹配模式后缩短字符串来工作。它使用函数 match() 来查找 pattern 匹配的位置。如果 m == 0,这意味着没有找到匹配项,因此我们可以跳出循环。我们在循环的每次迭代中递增 count,然后将 [=16=] 字符串重置为从索引 m + 1 开始的子字符串。

如果将其另存为a.awk,则可以

echo "joebobtomtomtomjoebobmike" | awk -v "pattern=tomtom" -f a.awk 

并且会输出2.

这可能对你有用 (GNU sed):

sed -r '/(tom)/!d;:a;s//\n/;ta;s/\n//'| wc -l

重复模式 tomtom 可以用正则表达式形式重写为 (tom) 然后用换行符替换重复模式的第一部分并循环直到找不到更多模式将给出许多指示重叠图案的线条。当打印结果时,必须考虑到这一点并从结果中减去,即必须删除最后一个(在本例中为第一个)换行符。当然,如果没有重复模式,结果必须为零,因此第一个 sed 命令。

您可以遍历字符串的长度,看看当前位置的子字符串是否是所需的文本:

string=joebobtomtomtomjoebobmiketomtomtom
match=tomtom
for ((i=0; i <= ${#string} - ${#match}; i++)); do
    [[ ${string:i:${#match}} == $match ]] && ((count++))
done
echo $count   # => 4