2012-02-03 223 views
10

我正在研究一个将被其他人使用的shell脚本,并且可能会吸收可疑字符串。它基于awk,所以作为一个基本的弹性测量,我希望awk输出以null结尾的字符串 - 从awk接收数据的命令可以避免来自包含空格或不包含空格的字符串的一定数量的破坏 - 经常发现英文字符。如何在Awk中输出以空字符结尾的字符串?

不幸的是,从基本的awk文档中,我没有得到如何告诉awk打印由ASCII空值而不是换行符终止的字符串。我如何告诉awk我想要以null结尾的字符串? AWK的


版本可能用于:

[[email protected]]$ awk --version 
awk version 20070501 

[[email protected]]$ awk -W version 
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan 

[[email protected]]$ awk -W version 
GNU Awk 3.1.7 

所以几乎是整个家庭的awk版本。如果我们需要整合一个版本,它可能会是GNU Awk,但是欢迎所有版本的回答,因为我可能必须使它适用于所有这些awk。哦,传统的脚本。

+0

目前为止发现的最佳指南:http://sandrotosi.blogspot.com/2011/09/print-nul-terminated-string-with-awk.html - 但这并不是一个完整的答案,而且随机的blogspot博客的搜索引擎优化比SO更少,所以一个好的答案对更多的人会有用。 – 2012-02-03 18:06:48

+2

尝试'awk -F $'\ 0'' – Kevin 2012-02-03 18:13:38

+0

凯文:想把它变成答案吗? – 2012-02-03 18:16:17

回答

15

好的,我明白了。

awk '{printf "%s\0", $0}' 

或者,使用ORS

awk -vORS=$'\0' // 
+1

当我将这些咒语的结果输入到'xargs -0'中时,它不会在awk插入的'\ 0'上分裂(通过分裂其他东西来测试)。 :( – 2012-02-03 19:55:46

+0

@SeanM第一个似乎不工作,但第二个工作对我来说,你确定问题出现在'awk'中吗?(尝试将输出保存到文件中) – Kevin 2012-02-03 20:06:04

+0

没有工作在这三个平台上,但是这让我发现我可以用Perl来做我想做的事 - 当我想用awk或sed做远程复杂的事情时,总是会发生这种情况。时间,并让我走上解决的道路,我接受它:) – 2012-02-03 20:39:29

-1

我从AWK解决打印ASCII 0。 我使用UNIX命令的printf “\​​ 000”

echo | awk -v s='printf "\000"' '{system(s);}' 
+0

'sh:1:语法错误:未终止的带引号的字符串' – 2015-06-27 16:39:14

9

有三种选择:

  1. 设置ORS为ASCII零: 其他解决方案具有awk -vORS=$'\0'但:
    $'\0'是构建特定于一些shell(bash,zsh)。
    所以:这个命令awk -vORS=$'\0'不适用于大多数旧的shell。

没有把它写的选项:awk 'BEGIN { ORS = "\0" } ; { print $0 }',但不会与大多数awk的版本。

  • 打印(printf)与字符\0awk '{printf("%s\0", $0)}'

  • 直接打印ASCII 0awk '{ printf("%s%c", $0, 0)}'

  • 测试所有与此代码替代:

    #!/bin/bash 
    
    test1(){ # '{printf("%s%c",$0,0)}'| 
        a='awk,mawk,original-awk,busybox awk' 
        IFS=',' read -ra line <<<"$a" 
        for i in "${line[@]}"; do 
         printf "%14.12s %40s" "$i" "$1" 
         echo -ne "a\nb\nc\n" | 
         $i "$1"| 
         od -cAn; 
        done 
    } 
    
    #test1 '{print}' 
    test1 'BEGIN { ORS = "\0" } ; { print $0 }' 
    test1 '{ printf "%s\0", $0}' 
    test1 '{ printf("%s%c", $0, 0)}' 
    

    ,我们得到这样的结果:

      awk  BEGIN { ORS = "\0" } ; { print $0 } a \0 b \0 c \0 
          mawk  BEGIN { ORS = "\0" } ; { print $0 } a b c 
        original-awk  BEGIN { ORS = "\0" } ; { print $0 } a b c 
        busybox awk  BEGIN { ORS = "\0" } ; { print $0 } a b c 
          awk      { printf "%s\0", $0} a \0 b \0 c \0 
          mawk      { printf "%s\0", $0} a b c 
        original-awk      { printf "%s\0", $0} a b c 
        busybox awk      { printf "%s\0", $0} a b c 
          awk    { printf("%s%c", $0, 0)} a \0 b \0 c \0 
          mawk    { printf("%s%c", $0, 0)} a \0 b \0 c \0 
        original-awk    { printf("%s%c", $0, 0)} a \0 b \0 c \0 
        busybox awk    { printf("%s%c", $0, 0)} a b c 
    

    正如上面可以看出,前两种解决方案在GNU AWK才起作用。

    最便携的是第三种解决方案:'{ printf("%s%c", $0, 0)}'

    没有解决方案在“busybox awk”中正常工作。

    用于此测试的版本是:

      awk> GNU Awk 4.0.1 
         mawk> mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan 
    original-awk> awk version 20110810 
         busybox> BusyBox v1.20.2 (Debian 1:1.20.0-7) multi-call binary. 
    
    +0

    许多祝福您指定您使用的版本!激发这个问题的问题早已变成不是我的,但我很高兴看到有人留下有益的,勤奋的答案。做得好。 – 2015-11-23 22:11:26

    1

    你也可以管你AWK的输出通过TR

    awk '{...code...}' infile | tr '\n' '\0' > outfile 
    

    只是测试,它的作品至少在Linux和FreeBSD。

    如果您不能使用换行符作为分隔符(例如,如果输出记录可以包含换行符),则可以使用其他保证不出现在记录中的其他字符,例如,代码为1的人:

    awk 'BEGIN { ORS="\001" } {...code...}' | tr '\001' '\0'