问题描述
我想计算文件中某些单词的出现次数。然后,我修改我的代码以另外计算与任何单词不匹配的行数。
例如,这是我的输入文件(test.txt):
select title
from books
where regexp_count(title,'\w+') > 2
这是我的代码:
fred
fred
fred
bob
bob
john
BILL
BILL
这很好用,并给了我这个输出:
awk '
/fred/ { count["fred"]++ }
/bob/ { count["bob"]++ }
/john/ { count["john"]++ }
END { for (name in count) print name,"was found on",count[name],"lines." }
' test.txt
现在,我想计数不匹配的行,所以我做了以下代码:
john was found on 1 lines.
bob was found on 2 lines.
fred was found on 3 lines.
awk '
found=0
/fred/ { count["fred"]++; found=1 }
/bob/ { count["bob"]++; found=1 }
/john/ { count["john"]++; found=1 }
if (found==0) { count["none"]++ }
END { for (name in count) print name,"lines." }
' test.txt
有什么想法为什么不起作用?
解决方法
考虑到您要打印仅出现1次的行,请尝试以下操作。您无需为每个数组值定义相同的变量,因为它可能产生假阳性结果。因此最好从条件中检查数组值中的计数值。
awk '
/fred/{ count["fred"]++ }
/bob/{ count["bob"]++}
/john/{ count["john"]++}
END{
for(name in count){
if(count[name]==1){
print name,"was found only 1 time ",name
}
}
}
' Input_file
注意: 另外,对于您的语法错误,awk
会先使用condition
然后是action
的方法,因此当条件为正确或错误,将按照以下说明执行所提到的动作:-> / test / {print“ something ....”}。在您的情况下,您直接提到的操作是为变量赋值,如果您使用{found=1}
,该变量将起作用,这只是为了回答语法错误部分。
关于使用条件,您有简单的语法错误。此声明无效:
awk 'if (found==0) { count["none"]++ }' # syntax error
因为if ()
并不构成可能在{}
之外存在的条件。您应该使用以下任一方法:
awk '{ if (found==0) count["none"]++ }'
或
awk 'found==0{ count["none"]++ }'
脚本开头的found = 0
也应放在{}
内,因为它也是一条语句。以下是一些有用的链接:patterns可以位于{}
的外部和前面,{}
的内部可以是actions。
您的脚本仅需进行必要的修改即可:
BEGIN { count["fred"]; count["bob"]; count["john"]; count["none"] }
{ found = 0 }
/fred/ { count["fred"]++; found=1 }
/bob/ { count["bob"]++; found=1 }
/john/ { count["john"]++; found=1 }
found==0{ count["none"]++ }
END { for (name in count) print name,"was found on",count[name]+0,"lines." }
- 已纠正两个语法错误。
- 添加了项目初始化,因为如果没有它,则如果根本没有“ fred”,则不会打印“ fred”的行。
- 添加了
count[name]+0
,因此,如果item为空字符串,则将打印零。
有两种方法可以实现您想要的。 OP提出的方法虽然可行,但实际上并不灵活。我们假设您有一个字符串str
,其中包含您感兴趣的单词:
awk -v str="fred bob john" \
'BEGIN{split(str,b);for(i in b) a[b[i]]; delete b }
($0 in a) {a[$0]++; c++}
END {for(i in a) print i,"was found",a[i]+0",times
print NR-c,"lines did not match" }' file1 file2 file3