一个奇怪的文本阻止awk命令工作

时间:2013-12-18 17:46:01

标签: bash shell awk

我使用awk命令来计算具有相同开头的行...

例如,在try1.txt中,文本为:

b : c
b : c

当我在终端中启动以下命令时:

awk -F ' : ' '$1=="b"{a[$2]++} END{for (i in a) print "  ", i,a[i]}' try1.txt

它会返回c 2,这很好,因为b : ctry1.txt中出现两次。

我的工具的输出是一个巨大的output.txt,比try1.txt复杂得多。 output.txt的某些部分包含以下字符:

^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^137

当进程被杀死时,系统会系统地编写它。我很好。但是,我意识到它会阻止awk运作良好。例如,在try2.txt中如下:

b : c
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^137
b : c

命令awk -F ' : ' '$1=="b"{a[$2]++} END{for (i in a) print " ", i,a[i]}' try2.txt返回c 1。也就是说,当它遇到奇数行^@^@^@^@^@时停止了。

我不知道如何防止系统写入奇数行^@^@^@^@^@,所以有谁知道如何修改awk命令来解决?

修改:我在^@中找到的output.txt似乎不是普通字符^@。以下是output.txt屏幕截图的一部分,显示在Emacs,但有问题:

enter image description here

修改:根据建议,我运行了xxd try2.txt,它提供了:

0000000: 6220 3a20 630a 0000 0000 0000 0000 0000  b : c...........
0000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000020: 0000 0000 0000 0000 0031 3337 0a62 203a  .........137.b :
0000030: 2063 0a  

3 个答案:

答案 0 :(得分:2)

^@可能代表二进制0 / NUL字符:

$ head -c10 /dev/zero > 10zero
$ cat -v 10zero 
^@^@^@^@^@^@^@^@^@^@$ 

某些面向文本的实用程序可能会将此视为文件末尾。

因此,由于您的输入文件是二进制文件,因此您应该先从中提取文本字符串,然后再对其进行操作:

$ strings try1.txt | awk -F ' : ' '$1=="b"{a[$2]++} END{for (i in a) print "  ", i,a[i]}'
   c 2
$

The strings command man page.(顺便提一下,当你google" man strings" - 你可能会得到一些你可能没有讨价还价的图像;-))


注意好奇 - 我在我的机器上完全重新创建了OP的try1.txt文件:

答案 1 :(得分:2)

许多Awk实现和一般的Unix文本处理工具处理空(零)字节的效果很差,因为它是用于构建这些工具的基本C库的字符串结束终止符。

Perl旨在处理任意输入;您可以尝试a2p将您的Awk脚本转换为Perl(但不要指望惯用,可维护或高效的Perl)。

或试试这个;

perl -lne '$a{$1}++ if (/^b : (.*?)\s*$/);  
    END { for $i (keys %a) { print " ", $i, " ", $a{$i} } }' try1.txt

答案 2 :(得分:1)

如果您想要的所有行都包含:,则可以尝试将$0 ~ /:/作为选择器。这是新的和改进的 awk语句(我在不同的行上写了它,因为它更容易跟踪花括号:

$ awk -F ' : ' '
{
    if ( $0 ~ /:/ && $1 == "b" )  {
    a[$2]++
    }
}
END {
    for (i in a) { 
    print "  ", i,a[i]
    }
}' try.txt

只要^@在他们自己的行上,这就有效。如果没有,您必须找出^@的字符类型。我怀疑它是一个空字符。如果是这样,您可能必须从文件中删除它们:

$ tr -d \0 < try.txt > try2.txt

这应该删除那些烦人的角色。然后,使用try2.txt进行输入。