awk 查找最常见的连续两个单词序列

awk 查找最常见的连续两个单词序列

我有一个名为“文件”的文本文件。我需要使用 awk 找到最常见的两个单词序列,而“this is”和“is this”在我们的计数中被认为是相等的。

示例文本:我的名字是,这是我们的文本是这样

预期输出:是这个 3

我使用了这个循环:

awk 'BEGIN{
    for(i=1;i<NF;i++) 
    a[$i OFS $(i+1)]++
    }' file

任何人都知道为什么会失败?

答案1

您的代码由于从未读取文件而失败。特殊BEGIN块被执行甚至打开命令行上命名的第一个输入文件进行读取(以及END最后一个之后的块)。您也没有代码的任何输出。

其他人已经给出了自己的解决方案,所以我将采用您的代码并稍微修改一下:

  1. 在普通块中运行代码以使其针对输入中的每一行执行。
  2. 使用END块查找数组中最常见的单词组合,并在处理完所有输入后进行输出。
  3. 确保每对中的单词始终按字典顺序使用。
awk '
    {
        for (i = 1; i < NF; i++)
            if ($i < $(i+1)) a[$i OFS $(i+1)]++
            else             a[$(i+1) OFS $i]++
    }
    END {
        for (words in a)
            if (a[words] > a[m]) m = words
        print m, a[m]
    }' file

根据给定的输入,这将打印is this 3

另一种实现是在读取文件时跟踪最大值,然后在末尾打印它:

awk '
    {
        for (i = 1; i < NF; ++i) {
            if ($i < $(i+1)) words = $i OFS $(i+1)
            else             words = $(i+1) OFS $i
            if (++count[words] > count[m]) m = words
        }
    }
    END { print m, count[m] }' file

不用担心数组:

awk '{ for (i = 1; i < NF; ++i) if ($i < $(i+1)) print $i, $(i+1); else print $(i+1), $i }' file | sort | uniq -c | sort -n | tail -n 1

也就是说,只需使用awk生成单词组合(每行一个),然后对它们进行排序,获取每个出现的次数,排序这些(按计数),然后选出计数最多的那个。虽然在大数据上进行调用sort会很昂贵,但是在电子邮件等小数据上运行,这就足够了。

答案2

尝试:

gawk '{
       for (i=2; i<=NF; i++) {
           delete arr; split($(i-1) "\n" $i, arr);
           asort(arr); s[arr[1] FS arr[2]]++
       };
     }
END { for(x in s) print s[x], x }' infile |sort -nr
3 is this
2 my name
1 our text
1 is text
1 is our
1 is name

split()函数将一对字符串(由空格(制表符/空格)分隔)添加到数组中,arr但每个字符串都在单独的行中\n

asort()函数对该arr数组进行排序;然后我们将结果添加到另一个数组中,该数组s以键作为一对已排序的字符串进行调用,并且如果再次出现,则为每个相同的字符串对增加值。

delete arr删除数组arr以供下一对字段的处理使用。

END我们循环数组s元素并打印看到的每对元素的计数以及对本身;sort -nr对结果进行排序并给出最重复的字符串对。

注意:在结果中,它不会告诉您是否有大多数is thisthis is全部只有其中之一,这只会告诉您所有排序结果is this作为本示例的结果。

答案3

正如 @kusalananda 指出的,你的主要错误是将所有代码放在 BEGIN 块中。因此,"this is" and "is this" are considered equal in our count.您需要执行类似的操作来保证您遇到的每一对单词都以特定(排序)顺序存储,无论它们在输入中出现的相对顺序如何:

awk '
{
    for(i=1; i<NF; i++) {
        pair = ($i > $(i+1) ? $i OFS $(i+1) : $(i+1) OFS $i)
        c = ++cnt[pair]
        max = (max > c ? max : c)
    }
}
END {
    for (pair in cnt) {
        c = cnt[pair]
        if ( c == max ) {
            print pair, c
        }
    }
}
' file
this is 3

相关内容