我现在正在使用awk
命令遇到一些问题。原始脚本是在MacOS上使用awk
开发的,然后被移植到Linux。 awk
那里显示了不同的行为。
我想做的是计算文件/tmp/test.uniq.txt
中通过/tmp/test.txt
提供的单个字符串的出现次数。
awk '{print $1, system("cat /tmp/test.txt | grep -o -c " $1)}' /tmp/test.uniq.txt
Mac提供了预期的输出,例如:
test1 2
test2 1
输出在一行中,字符串和出现次数用空格隔开。
Linux提供的输出如下:
2
test1 1
test2
输出不在一行中,首先打印系统命令的输出。
样本输入: test.txt看起来像:
test1 test test
test1 test test
test2 test test
test.uniq.txt看起来像:
test1
test2
答案 0 :(得分:2)
正如评论所建议的那样,不建议使用grep
和cat
等功能,因为system
是可以执行大多数任务的完整语言。
您可以使用以下awk
命令来替换您的awk
功能:
cat | grep
awk 'FNR == NR {a[$1]=0; next} {for (i=1; i<=NF; i++) if ($i in a) a[$i]++}
END { for (i in a) print i, a[i] }' uniq.txt test.txt
请注意,由于您的问题指出样本数据可能不同,因此此输出与计数test1 2
test2 1
不匹配。
参考:
答案 1 :(得分:1)
在我看来,您似乎要计算uniq
文件中包含每个唯一字符串的行数。但是您的操作方式很尴尬,而且正如您所展示的,awk的版本之间也不一致。
以下内容可能会更好一些:
$ awk '
NR==FNR {
a[$1]
next
}
{
for (i in a) {
if ($1~i) {
a[i]++
}
}
}
END {
for (i in a)
printf "%6d\t%s\n",a[i],i
}
' test.uniq.txt test.txt
2 test1
1 test2
这会将您的uniq
文件加载到数组中,然后对于文本文件中的每一行,逐步遍历数组以计算匹配项。
请注意,这些字符串被作为正则表达式进行比较,没有单词边界,因此test1
也将被算作test12
的一部分。
答案 2 :(得分:0)
另一种方法可能是使用grep
+ sort
+ uniq
:
grep -o -w -F -f uniq.txt test.txt | sort | uniq -c
这是一条管道,但很短
来自man grep
:
-F
,--fixed-strings
,--fixed-regexp
将PATTERN解释为固定字符串列表,由换行符分隔,其中任何一个都将被匹配。 ({-F
由POSIX指定,--fixed-regexp
是已过时的别名,请不要在新脚本中使用它。)-f FILE
,--file=FILE
从FILE中获取模式,每行一个。空文件包含零个模式,因此不匹配。 ({-f
由POSIX指定。)-o
,--only-matching
仅打印匹配行的匹配(非空)部分,每个这样的部分都在单独的输出行上。-w
,--word-regexp
仅选择包含构成整个单词的匹配项的行。测试是匹配的子字符串必须在行的开头,或者必须在非单词组成字符之前。同样,它必须在行的末尾,或后跟非单词组成字符。单词构成的字符是字母,数字和下划线。