AWK 问题:计数 "non-matches"
AWK issue : counting "non-matches"
我想计算文件中某些单词的出现次数。然后我修改我的代码以另外计算有多少行与任何单词不匹配。
例如这是我的输入文件 (test.txt):
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, "was found on", count[name], "lines." }
' test.txt
我在 if 语句中遇到这样的错误:
awk: syntax error at source line 6
context is
>>> if <<< (found==0) { count["none"]++; }
awk: bailing out at source line 8
知道为什么这不起作用吗?
考虑到您要打印仅出现 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 and inside {}
we have the 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
所以如果项目是空字符串,将打印零。
有几种方法可以实现您想要的效果。虽然 OP 提供的方法有效,但它并不真正灵活。我们假设您有一个字符串 str
,其中包含您感兴趣的单词:
awk -v str="fred bob john" \
'BEGIN{split(str,b);for(i in b) a[b[i]]; delete b }
([=10=] in a) {a[[=10=]]++; c++}
END {for(i in a) print i,"was found",a[i]+0", times
print NR-c, "lines did not match" }' file1 file2 file3
我想计算文件中某些单词的出现次数。然后我修改我的代码以另外计算有多少行与任何单词不匹配。
例如这是我的输入文件 (test.txt):
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, "was found on", count[name], "lines." }
' test.txt
我在 if 语句中遇到这样的错误:
awk: syntax error at source line 6
context is
>>> if <<< (found==0) { count["none"]++; }
awk: bailing out at source line 8
知道为什么这不起作用吗?
考虑到您要打印仅出现 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 and inside {}
we have the 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
所以如果项目是空字符串,将打印零。
有几种方法可以实现您想要的效果。虽然 OP 提供的方法有效,但它并不真正灵活。我们假设您有一个字符串 str
,其中包含您感兴趣的单词:
awk -v str="fred bob john" \
'BEGIN{split(str,b);for(i in b) a[b[i]]; delete b }
([=10=] in a) {a[[=10=]]++; c++}
END {for(i in a) print i,"was found",a[i]+0", times
print NR-c, "lines did not match" }' file1 file2 file3