awk打印行问题

时间:2018-06-27 13:38:31

标签: linux macos awk

我现在正在使用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

3 个答案:

答案 0 :(得分:2)

正如评论所建议的那样,不建议使用grepcat等功能,因为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             仅选择包含构成整个单词的匹配项的行。测试是匹配的子字符串必须在行的开头,或者必须在非单词组成字符之前。同样,它必须在行的末尾,或后跟非单词组成字符。单词构成的字符是字母,数字和下划线。
  •