代码之家  ›  专栏  ›  技术社区  ›  mmonem

如何使用awk提取引用字段?[复制品]

  •  6
  • mmonem  · 技术社区  · 14 年前

    这个问题已经有了答案:

    我正在使用

    awk '{ printf "%s", $3 }'
    

    从以空格分隔的行中提取一些字段。当然,当字段内有空格引用时,会得到部分结果。有人能提出解决办法吗?

    4 回复  |  直到 9 年前
        1
  •  1
  •   schot    14 年前

    这实际上相当困难。我想出了以下几点 awk 手动拆分行并将所有字段存储在数组中的脚本。

    {
        s = $0
        i = 0
        split("", a)
        while ((m = match(s, /"[^"]*"/)) > 0) {
            # Add all unquoted fields before this field
            n = split(substr(s, 1, m - 1), t)
            for (j = 1; j <= n; j++)
                a[++i] = t[j]
            # Add this quoted field
            a[++i] = substr(s, RSTART + 1, RLENGTH - 2)
            s = substr(s, RSTART + RLENGTH)
            if (i >= 3) # We can stop once we have field 3
                break
        }
        # Process the remaining unquoted fields after the last quoted field
        n = split(s, t)
        for (j = 1; j <= n; j++)
            a[++i] = t[j]
        print a[3]
    }
    
        2
  •  6
  •   ghostdog74    14 年前

    下次显示输入文件和所需的输出。要获取引用字段,

    $ cat file
    field1 field2 "field 3" field4 "field5"
    
    $ awk -F'"' '{for(i=2;i<=NF;i+=2) print $i}' file
    field 3
    field5
    
        3
  •  1
  •   benj    10 年前

    这是解决这个问题的一个可能的替代方案。它的工作原理是找到以引号开头或结尾的字段,然后将它们连接在一起。最后,它会更新字段和nf,因此如果在合并之后放置更多的模式,则可以使用所有正常的awk特性处理(新)字段。

    我认为这只使用POSIXawk的特性,不依赖于gawk扩展,但我不完全确定。

    # This function joins the fields $start to $stop together with FS, shifting
    # subsequent fields down and updating NF.
    #
    function merge_fields(start, stop) {
        #printf "Merge fields $%d to $%d\n", start, stop;
        if (start >= stop)
            return;
        merged = "";
        for (i = start; i <= stop; i++) {
            if (merged)
                merged = merged OFS $i;
            else
                merged = $i;
        }
        $start = merged;
    
        offs = stop - start;
        for (i = start + 1; i <= NF; i++) {
            #printf "$%d = $%d\n", i, i+offs;
            $i = $(i + offs);
        }
        NF -= offs;
    }
    
    # Merge quoted fields together.
    {
        start = stop = 0;
        for (i = 1; i <= NF; i++) {
            if (match($i, /^"/))
                start = i;
            if (match($i, /"$/))
                stop = i;
            if (start && stop && stop > start) {
                merge_fields(start, stop);
                # Start again from the beginning.
                i = 0;
                start = stop = 0;
            }
        }
    }
    
    # This rule executes after the one above. It sees the fields after merging.
    {
        for (i = 1; i <= NF; i++) {
            printf "Field %d: >>>%s<<<\n", i, $i;
        }
    }
    

    在输入文件上,如:

    thing "more things" "thing" "more things and stuff"
    

    它产生:

    Field 1: >>>thing<<<
    Field 2: >>>"more things"<<<
    Field 3: >>>"thing"<<<
    Field 4: >>>"more things and stuff"<<<
    
        4
  •  0
  •   Alan Swindells    9 年前

    如果您只是在寻找一个特定的字段,那么

    $ cat file
    field1 field2 "field 3" field4 "field5"
    
    awk -F"\"" '{print $2}' file
    

    作品。它将文件拆分为“,因此上面示例中的第二个字段就是您想要的字段。