【问题标题】:How to print the unpredicted fields - awk如何打印不可预测的字段 - awk
【发布时间】:2016-02-15 19:11:38
【问题描述】:

我正在尝试通过 awk 解析下面的输入。 如果只有 3 对项目意味着如果有 ID=34、ID2=35、COL3="231,则输出看起来不错。因为我在 printf 中只使用了 4 个字符串变量。 但是,项目的数量(ID/ID2/COL3)会有所不同。这就是问题所在。

即使项目数量不固定,如何打印所有这些项目?

输入

!{ID=34, ID2=35, COL3="231"}
>
!{ID=99, ID2=23}
>
!{ID=18, ID2=87}
<
@{ID=11, ID2=22, COL3="231",COL4="098", COL5="AAA", COL6="BBB"}
UPD1

Awk

BEGIN { FS="[}{[:space:] ]+"; RS="!|@" }
NR > 1 { 
printf "%s%s%s#%s\n", $2, $3, $4, $5;
}

输出

ID=34,ID2=35,COL3="231"#>
ID=99,ID2=23>#
ID=18,ID2=87<#
ID=11,ID2=22,COL3="231",COL4="098",#COL5="AAA",

期望的输出

ID=34,ID2=35,COL3="231"#>
ID=99,ID2=23#>
ID=18,ID2=87#<
ID=11,ID2=22,COL3="231",COL4="098",COL5="AAA",COL6="BBB"#UPD1

第二个期望的输出

!#ID=34,ID2=35,COL3="231"#>
!#ID=99,ID2=23#>
!#ID=18,ID2=87#<
@#ID=11,ID2=22,COL3="231",COL4="098",COL5="AAA",COL6="BBB"#UPD1

【问题讨论】:

    标签: awk


    【解决方案1】:

    这是一种非常奇怪的格式。我必须(重新)安装 GNU Awk(4.1.3)才能得到你看到的输出。 BSD (Mac OS X) awk 无法识别多字符 RS 值中的 @ — 请参阅下面的注释。

    AFAICT,此代码产生您使用 GNU Awk 寻求的输出。它以# 标记为该行的最后一个非空白字段添加前缀。将OFS 设置为空字符串会输出字段之间没有空格的字段。

    script.awk

    BEGIN   { FS="[}{[:space:]]+"; RS="!|@"; OFS="" }
    NR > 1  {
        # printf "%s%s%s#%s\n", $2, $3, $4, $5;
        for (i = NF; i > 1; i--)
        {
            if ($i != "")
            {
                $i = "#" $i
                break
            }
        }
        print
    }
    

    示例运行:

    $ gawk -f script.awk data
    ID=34,ID2=35,COL3="231"#>
    ID=99,ID2=23#>
    ID=18,ID2=87#<
    ID=11,ID2=22,COL3="231",COL4="098",COL5="AAA",COL6="BBB"#UPD1
    $
    

    对于同一个数据文件,BSD awk 会生成:

    $ awk -f script.awk data
    ID=34,ID2=35,COL3="231"#>
    ID=99,ID2=23#>
    ID=18,ID2=87<@ID=11,ID2=22,COL3="231",COL4="098",COL5="AAA",COL6="BBB"#UPD1
    $
    

    它忽略了RS 值中的@(以及|,但数据并未证明这一点)。但是,根据awk 的 POSIX 规范,这是合法的。

    RS

    RS的字符串值的第一个字符应为输入记录分隔符;默认为&lt;newline&gt;。如果 RS 包含多个字符,则结果未指定。如果 RS 为空,则记录由由 &lt;newline&gt; 加上一个或多个空行组成的序列分隔,前导或尾随空行不应导致输入的开头或结尾处为空记录,&lt;newline&gt; 应始终是字段分隔符,无论 FS 的值是多少。

    GNU Awk 扩展是一种有效的未指定行为;忽略额外字符的 BSD Awk 行为也是有效的未指定行为。

    【讨论】:

    • 太棒了!我们是否也可以像第二个期望输出一样同时打印 RS(! 或 @)?
    • 感谢您的宝贵时间。
    【解决方案2】:

    我想知道您是否可能对解决字段、字段分隔符和字段数量感到困惑,而此时可能会以不同的方式看待问题...

    如果你忘记了字段和字段数怎么办,并说 “如果该行包含大括号,删除所有空格、大括号、at 符号并保存该行,否则打印带有哈希符号的保存行和当前行”

    awk '/{/ {gsub(/[ {}!@]/,"");m=$0;next} {print m"#"$0}' file
    
    ID=34,ID2=35,COL3="231"#>
    ID=99,ID2=23#>
    ID=18,ID2=87#<
    ID=11,ID2=22,COL3="231",COL4="098",COL5="AAA",COL6="BBB"#UPD1
    

    【讨论】:

    • 谢谢。你能告诉我如何使用 awk 脚本来做到这一点吗?
    • 只需将所有awk 命令减去单引号放入文件中,就像您自己做的那样。
    • 好的。非常简单的解决方案。非常感谢。
    猜你喜欢
    • 2013-03-13
    • 2015-11-04
    • 2012-02-27
    • 1970-01-01
    • 2013-08-29
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    相关资源
    最近更新 更多