如何计算多个重叠的字符串并获得每行的总出现次数(awk或其他任何内容)

时间:2015-07-02 00:10:31

标签: bash awk substr

我有一个这样的输入文件:

315secondbin    x12121321211332123x
315firstbin 3212212121x
315thirdbin 132221312
316firstbin 121
316secondbin    1212

我想要做的是计算在计算重叠的每一行中存在多少个不同字符串(例如“121”和“212”)的实例。所以我的预期输出是:

6
5
0
1
2

所以我稍微修改了一些来自另一个线程的awk以使用OR运算符,希望它可以计算满足任一条件的所有内容:

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

不幸的是,我的输出是:

8
4
0
2
3

但是,如果我遗漏OR,它就完全算了。我做错了什么?

另外,我通过运行:

在ymaz.txt文件上运行脚本
 cat ymaz.txt | awk -v "pattern=" -f count3.awk

作为替代方法,我试过这个:

{
count = 0
$0 = tolower($0)
while (length() > 0) {
    m = match($0, /212/)
y = match($0, /121/)
    if ((m == 0) && (y == 0))
         break
    count++
    $0 = substr($0, (m + 1) + (y + 1))
}
print count
}

但我的输出是这样的:

1
1
0
1
1

我做错了什么?我知道我应该理解代码而不是一起剪切和粘贴内容,但这是我的技能水平。

当我在那里没有OR时(即我只是搜索1个字符串),它完美无缺。

2 个答案:

答案 0 :(得分:3)

你太复杂了:

{
    count=0
    while ( match($0,/121|212/) ) {
        count++
        $0=substr($0,RSTART+1)
    }
    print count
}

$ awk -f tst.awk file
6
5
0
1
2

你的根本问题是你正在使用正则表达式混淆一个条件。可以将正则表达式与字符串进行比较以形成条件,当有问题的字符串为$ 0时,您可以将其保留,只使用regexp作为$0 ~ regexp的简写,但在该上下文中是什么&#39被测试仍然是一个条件。 match()的第二个arg是正则表达式,而不是条件。 |是正则表达式中的or运算符,而||是条件中的or运算符。 /.../是正则表达式分隔符。

/foo/是正则表达式

$0 ~ /foo/是一个条件

条件上下文中的

/foo/$0 ~ /foo/的简写,但在任何其他上下文中只是一个正则表达式。

条件上下文中的

/foo/ || /bar$0 ~ /foo/ || $0 ~ /bar/的简写,但是作为匹配()的第二个参数,awk实际上假定您打算写:

match($0,($0 ~ /foo/ || $0 ~ /bar/))

即。它将针对foo或bar测试当前记录,如果为true,则该条件的计算结果为1,然后将该1赋予match(),因为它是第二个arg。

查找

$ echo foo | gawk 'match($0,/foo/||/bar/)'        
$ echo foo | gawk '{print /foo/||/bar/}'  
1
$ echo 1foo | gawk 'match($0,/foo/||/bar/)'       
1foo

获取由Arnold Robbins撰写的Effective Awk Programming,4th Edition。

答案 1 :(得分:3)

Perl方式:

perl -lpe '$_ = () = m/(?=121|212)/go'

输出:

6
5
0
1
2