执行此操作时遇到一些问题。输出需要采用以下格式:在每一行上,首先打印一个单词,后跟一个冒号“:”,然后是一个空格,然后是该单词出现的行号列表(用逗号分隔)。如果一个单词在一行中出现多次,则该行应该只报告一次。
命令行: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 是否有一个 native 函数可以解释错误的字符,例如标点符号、数字、[]、() 等...
(编辑:gsub(regexp, replacement, target) 可以从文本中省略这些错误字符。
Sample INPUT: I would like to print out each word, and the corresponding lines which the word occurs on. I need to make sure I omit the punctuation's from the strings when printing them out. As well, I need to make sure if the word occurs more than once on a line not to print the line number twice.
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)
最佳答案
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
它是如何工作的
该程序使用三个变量:i
, u
和cnt
。 u
用于在每行上创建唯一的单词列表。 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
关于shell - 使用 awk 记录给定文件中每个单词出现的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26349874/