【问题标题】:Tab separated values in awkawk 中的制表符分隔值
【发布时间】:2011-07-19 10:57:07
【问题描述】:

如何从 TAB 分隔的字符串中选择第一列?

# echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F'\t' '{print $1}'

上面将返回整行,而不仅仅是“LOAD_SETTLED”,如预期的那样。

更新:

我需要更改制表符分隔值中的第三列。 以下不起作用。

echo $line | awk 'BEGIN { -v var="$mycol_new" FS = "[ \t]+" } ; { print $1 $2 var $4 $5 $6 $7 $8 $9 }' >> /pdump/temp.txt

但是,如果分隔符是逗号而不是制表符,这将按预期工作。

echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt

【问题讨论】:

  • awk 'BEGIN { FS = "[ \t]+" } ; { print $1 }' # 这就是我要找的。我的谷歌搜索正确吗? :)
  • 感谢这条评论,我发现:awk 'BEGIN {FS="\t"}; {print $1,FS,$2,FS,$3}' myFile.txt 打印前三列的制表符分隔值。
  • 或者只是awk 'BEGIN {OFS="\t"}; {print $1,$2,$3}'
  • GNU 和 BSD awk 都支持 -v 设置变量。在 内联程序 中使用BEGIN {FS="\t"} 是很丑陋的,而且您尝试做出的任何开源贡献都可能会遭到反对。只有在编写程序文件 时才这样做。此外,不鼓励使用-F 而不是-v FS=,因为后者清楚地表明只有FS 被设置,而不是OFS。对最后一点的困惑首先是导致这篇文章的原因。这就是为什么“好风格”很重要。
  • 拜托,没有人应该做@Wok 演示的事情。您不会在输出中枚举 [Input] 字段分隔符。您可以通过 OFS 变量指定输出字段分隔符。

标签: awk


【解决方案1】:

确保它们确实是标签!在 bash 中,您可以使用 C-v TAB

插入选项卡
$ echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F$'\t' '{print $1}'
LOAD_SETTLED

【讨论】:

    【解决方案2】:
    echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -v var="test" 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" var "\t" $3 }'
    

    【讨论】:

      【解决方案3】:

      您需要将OFS 变量(输出字段分隔符)设置为制表符:

      echo "$line" | 
      awk -v var="$mycol_new" -F'\t' 'BEGIN {OFS = FS} {$3 = var; print}'
      

      (确保在 echo 语句中引用 $line 变量)

      【讨论】:

      • $'\t'中的$是什么目的?
      • Advanced Bash Scripting Guide 回答我自己的问题:$' ...' 引用的字符串扩展结构是一种使用转义的八进制或十六进制值的机制...,例如,quote=$' \042'。
      • @AmrMostafa,太糟糕了,该指南有一个误导性的解释,导致人们认为您不需要 $'\t' 中的 $Greg's wiki 更好:“其中,$'...' 是最常见的,除了反斜杠转义组合按照 ANSI C 标准的规定进行扩展之外,它的作用就像单引号一样”。
      • 事后看来,$'\t' 是不必要的。 awk 将字符串 "\t" 理解为制表符
      • 开源贡献者,求求你了,请不要提交awk -F $'\t' 'BEGIN {OFS = FS} …'之类的东西。那应该是awk -v FS='\t' -v OFS='\t' '…'。这可能看起来很迂腐,但不一致会增加后来的贡献者引入错误的机会,因为他们误解了您的代码。
      【解决方案4】:

      这应该行不通吗?

      echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk '{print $1}'
      

      【讨论】:

        【解决方案5】:

        您可以设置字段分隔符:

        ... | awk 'BEGIN {FS="\t"}; {print $1}'
        

        优秀的阅读:

        https://docs.freebsd.org/info/gawk/gawk.info.Field_Separators.html

        【讨论】:

        • 实现这一目标的最简单方法。顺便说一句,对我来说最清楚......
        【解决方案6】:

        用途:

        awk -v FS='\t' -v OFS='\t' ...
        

        来自one of my scripts 的示例。

        我使用FSOFS 变量来操作以制表符分隔的BIND 区域文件:

        awk -v FS='\t' -v OFS='\t' \
            -v record_type=$record_type \
            -v hostname=$hostname \
            -v ip_address=$ip_address '
        $1==hostname && $3==record_type {$4=ip_address}
        {print}
        ' $zone_file > $temp
        

        这是一种简洁易读的方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-04
          • 2013-03-08
          • 2013-08-17
          • 2020-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多