使用awk记录给定文件中每个单词出现的行

时间:2014-10-13 22:27:23

标签: shell awk scripting gawk scripting-language

这样做有一些问题。输出需要具有以下格式:在每一行上,首先打印一个单词,然后是冒号“:”,然后是空格,然后是单词出现的行号列表(用逗号分隔)。如果一个单词多次出现在一行中,它应该只报告该行的一次。

命令行:index.awk test1.txt> new.output.txt

我的代码(目前):

    #!/bin/awk -f


Begin {lineCount=1}                    # start line count at 1

{         
    for (i = 1; i <= NF; i++)          # loop through starting with postition 1
       for ( j = 2; j <= NF; j++)      # have something to compare  
          if ( $i == $j )              # see if they match
              print $i ":" lineCount   # if they do print the word and line number
              lineCount++              # increment the line number

}

您会在示例输出中注意到它完全跳过输入文本文件的第一行。它从那里正确计算。如果多次出现,我该如何打印单词出现?同样,是否存在awk的原生函数,可以解释标点符号,数字,[],()等错误字符...

(编辑:gsub(regexp,replacement,target)可以从文本中省略这些错误字符。

  

示例INPUT:我想打印出每个单词,然后是   单词出现的相应行。我需要确定   打印出来时,我省略了字符串中的标点符号。如   好吧,我需要确保这个词在一行上出现不止一次   不要两次打印行号。

SAMPLE OUTPUT: 

I:
would:
like:
to:
print:
out:
each:
word:
and,:
the:1
corresponding:
lines:
which:
the:
word:
occurs:
on.:
I:1
need:1
to:1
make:1
sure:1
.....ect (outputs the line numbers correctly from here)

1 个答案:

答案 0 :(得分:3)

awk '{delete u;for (i=1;i<=NF;i++) u[$i]=1; for (i in u) cnt[i]=cnt[i]NR","} END{for (i in cnt) {sub(/,$/,"",cnt[i]); printf "%s: %s\n",i,cnt[i]}}' input

作为一个例子(文字比你的例子短一些):

$ cat file
I and I and I went
here and here and there
and then home

$ awk '{delete u;for (i=1;i<=NF;i++) u[$i]=1; for (i in u) cnt[i]=cnt[i]NR","} END{for (i in cnt) {sub(/,$/,"",cnt[i]); printf "%s: %s\n",i,cnt[i]}}' file
there: 2
went: 1
here: 2
and: 1,2,3
then: 3
I: 1
home: 3

如何运作

该计划使用三个变量:iucntu用于在每行上创建唯一的单词列表。 cnt用于跟踪每个单词的行号。 i用作循环中的临时变量。

此代码使用awk隐式循环遍历文件中每一行的事实。读取最后一行后,执行END子句,显示结果。

依次考虑每个命令:

  • delete u

    在每一行的开头,我们希望数组u为空。

  • for (i=1;i<=NF;i++) u[$i]=1

    在数组u中为该行中的每个单词创建一个条目。

  • for (i in u) cnt[i]=cnt[i]NR","

    对于该行中的每个单词,将当前行号添加到数组cnt

  • END{for (i in cnt) {sub(/,$/,"",cnt[i]); printf "%s: %s\n",i,cnt[i]}

    处理完最后一行后,打印出数组cnt中的每个条目。 cnt中的每个条目都有一个额外的尾随逗号。使用sub命令删除该逗号。然后printf格式化输出。

加细

假设我们想要忽略案例中的差异。为此,我们可以将所有单词转换为小写:

$0=tolower($0)

如果我们还想忽略标点符号,我们可以将其删除:

gsub(/[-.,"!?/]/," ")

全部放在一起:

awk '{delete u;$0=tolower($0);gsub(/[-.,"!?/]/," ");for (i=1;i<=NF;i++) u[$i]=1; for (i in u) cnt[i]=cnt[i]NR","} END{for (i in cnt) {sub(/,$/,"",cnt[i]); printf "%s: %s\n",i,cnt[i]}}' file