【问题标题】:Count overlapping occurences of a repeated string using grep/linux/bash使用 grep/linux/bash 计算重复字符串的重叠出现次数
【发布时间】:2015-06-04 01:05:15
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

  • 完成了!谢谢。您的回答和 potong 都有效地回答了我的问题。

标签: linux bash shell sed grep


【解决方案1】:

你可以使用这个 awk 脚本

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

说明

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

如果你把它保存为a.awk,你可以这样做

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

它会输出2

【讨论】:

  • 感谢这很好用(而且相对较快)。有什么方法可以让 match 命令忽略大小写?
  • 您可以先使用tolower()$0 转换为小写。另请注意,我通过使用变量pattern 使脚本更具可移植性,您将其作为选项传递给脚本。
【解决方案2】:

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

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

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

【讨论】:

  • 这行得通!有什么方法可以让 sed 忽略换行符(没有管道到 tr 来删除换行符)?例如。 echo -e 'tomtomtom\ntomtom' | sed -r '/(tom)\1/!d;:a;s//\n\1/;ta;s/\n//'| wc -l 返回 3 但我希望它返回 4
  • @Floris 要删除换行符,您可以通过在现有命令前面加上 :b;$!{N;bb};s/\n//g; 将整个文件啜饮到内存中
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2020-06-02
    • 1970-01-01
    • 2012-05-31
    • 2011-03-02
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    相关资源
    最近更新 更多