【问题标题】:Use Awk to extract substring使用 awk 提取子字符串
【发布时间】:2013-04-09 01:35:00
【问题描述】:

给定一个aaa0.bbb.ccc 格式的主机名,我想提取. 之前的第一个子字符串,在本例中为aaa0。我使用以下 awk 脚本来执行此操作,

echo aaa0.bbb.ccc | awk '{if (match($0, /\./)) {print substr($0, 0, RSTART - 1)}}'

虽然在一台机器上运行的脚本A 产生aaa0,但在机器B 上运行只产生aaa,最后没有0。两台机器都运行Ubuntu/Linaro,但A 运行较新版本的awk(gawk 3.1.8 版,而B 旧版awk(mawk 1.2 版)

一般来说,我在问,如何编写一个兼容的 awk 脚本来执行相同的功能......

【问题讨论】:

    标签: bash awk


    【解决方案1】:

    您根本不需要任何外部命令,只需在 bash 中使用参数扩展:

    hostname=aaa0.bbb.ccc
    echo ${hostname%%.*}
    

    【讨论】:

      【解决方案2】:

      我一般都在问,如何编写兼容的 awk 脚本 执行相同的功能...

      解决您的问题很容易。 (查看其他人的答案)。

      如果您想编写一个可移植到任何 awk 实现和版本(gawk/nawk/mawk...)的 awk 脚本,即使使用 --posix (gawk) 也非常困难

      例如:

      • 一些 awk 以字符的形式作用于字符串,一些以字节为单位
      • 有些支持\x转义,有些不支持
      • FS 解释器的工作方式不同
      • 关键词/保留词缩写限制
      • 一些操作员限制,例如**
      • 即使是相同的 awk impl。 (例如 gawk),4.0 和 3.x 版本也有区别。
      • 某些功能的实现也不同。 (你的问题就是一个例子,见下文)

      以上所有观点只是笼统地说。回到您的问题,您的问题仅与 awk 的基本功能有关。 awk '{print $x}' 这样的行适用于所有 awks。

      您的 awk 行在 gawk 和 mawk 上表现不同的原因有两个:

      • 您使用的substr() 功能错误。这是主要原因。你有substr($0, 0, RSTART - 1)0应该是1,不管你使用哪个awk。 awk 数组、字符串 idx 等都是从 1 开始的。

      • gawk 和 mawk 以不同方式实现 substr()

      【讨论】:

        【解决方案3】:

        你不需要 awk 来做这个......

        echo aaa0.bbb.ccc | cut -d. -f1
        cut -d. -f1 <<< aaa0.bbb.ccc
        
        echo aaa0.bbb.ccc | { IFS=. read a _ ; echo $a ; }
        { IFS=. read a _ ; echo $a ; } <<< aaa0.bbb.ccc 
        
        x=aaa0.bbb.ccc; echo ${x/.*/}
        

        较重的选项:

        sed:
        echo aaa0.bbb.ccc | sed 's/\..*//'
        sed 's/\..*//' <<< aaa0.bbb.ccc 
        awk:
        echo aaa0.bbb.ccc | awk -F. '{print $1}'
        awk -F. '{print $1}' <<< aaa0.bbb.ccc 
        

        【讨论】:

          【解决方案4】:

          或者直接使用 cut:

          echo aaa0.bbb.ccc | cut -d'.' -f1
          

          【讨论】:

            【解决方案5】:

            您只想使用-F 选项将字段分隔符设置为. 并打印第一个字段:

            $ echo aaa0.bbb.ccc | awk -F'.' '{print $1}'
            aaa0
            

            同样的事情,但使用 cut:

            $ echo aaa0.bbb.ccc | cut -d'.' -f1
            aaa0
            

            或者sed:

            $ echo aaa0.bbb.ccc | sed 's/[.].*//'
            aaa0
            

            grep:

            $ echo aaa0.bbb.ccc | grep -o '^[^.]*'
            aaa0
            

            【讨论】:

            • 如何使用 grep 获得 bbb?
            • sed 的情况下,您可以转义.,即echo aaa0.bbb.ccc | sed 's/\..*//'
            猜你喜欢
            • 2015-05-10
            • 1970-01-01
            • 1970-01-01
            • 2018-12-05
            • 1970-01-01
            • 1970-01-01
            • 2014-10-20
            • 2021-02-27
            • 1970-01-01
            相关资源
            最近更新 更多