【问题标题】:How to format the output of a program using awk, transforming the first column but keeping the rest as if?如何使用 awk 格式化程序的输出,转换第一列但保持其余部分不变?
【发布时间】:2021-10-23 19:11:03
【问题描述】:

我需要格式化go tool cover 的输出,这样我就可以将第一列除以/,这样我就只得到最后两个值,但将其余的输出保留为原始值。

原始输出如下所示:

$ go tool cover -func=coverage.out
github.com/company/utils/common.go:6:              IsFoo                   100.0%
github.com/company/utils/logger.go:118:            maskFoo                 100.0%
github.com/company/utils/logger.go:127:            createFoo               100.0%
github.com/company/utils/logger.go:132:            CreateFakeFoo           100.0%
github.com/company/utils/foo_validaiton.go:43:     IsFoo                   100.0%
github.com/company/utils/foo_validaiton.go:49:     GreaterThanFoo          100.0%
github.com/company/utils/yaml.go:39:               closeFOO                100.0%
total:                                             (statements)            100.0%

我尝试使用 awk 拆分第一列并仅获取 utils/file.go 部分,但列未对齐。

$ go tool cover -func=coverage.out | awk '{split($1, a, "/"); print a[4]"/"a[5]"\t"$2"\t"$3}'

utils/common.go:6:  IsFoo  100.0%
utils/logger.go:118:  maskFoo  100.0%
utils/logger.go:127:  createFoo  100.0%
utils/logger.go:132:  CreateFakeFoo  100.0%
utils/foo_validaiton.go:43:  IsFoo  100.0%
utils/foo_validaiton.go:49:  GreaterThanFoo  100.0%
utils/yaml.go:39:  closeFOO  100.0%
/  (statements)  100.0%

如何使用 awk 或其他 cli 工具归档以下输出?

utils/common.go:6:              IsFoo                   100.0%
utils/logger.go:118:            maskFoo                 100.0%
utils/logger.go:127:            createFoo               100.0%
utils/logger.go:132:            CreateFakeFoo           100.0%
utils/foo_validaiton.go:43:     IsFoo                   100.0%
utils/foo_validaiton.go:49:     GreaterThanFoo          100.0%
utils/yaml.go:39:               closeFOO                100.0%
total:                          (statements)            100.0%

【问题讨论】:

    标签: awk


    【解决方案1】:

    你可以使用sed:

    go ... | sed 's~\([^/]\{1,\}/\)\{2\}~~'
    

    要获得良好对齐的输出,请再次通过管道传输到 column -t

    go ... | sed 's~\([^/]\{1,\}/\)\{2\}~~' | column -t
    

    PS:当然也可以使用 awk,但对于纯正则表达式搜索,替换操作 sed 可能就足够了:

    awk '/\//{sub(/[^\/]+\/{2}/,"",$1)}1' | column -t
    

    如果要使用拆分:

    go ... \
        | awk '{if(split($1, a, "/")>1){print a[3]"/"a[4]"\t"$2"\t"$3}else{print}}' \
        | column -t
    

    【讨论】:

    • 我更喜欢这个命令而不是 awk 选项。我检查了一下,如果我在它之后使用| column -t,我拥有的 awk 命令可以正常工作。谢谢!
    【解决方案2】:

    如果您想保留由 / 分隔的最后 2 个值与第一列,您可以使用模式匹配最后一次出现正斜杠之前和之后的 1 个或多个字符,并将匹配设置为再次显示第 1 列的值。

    从输入 file 加载示例数据:

    awk 'match($1, /[^\/]+\/[^\/]+$/) {
      $1 = substr($1, RSTART, RLENGTH)
    }1' file | column -t
    

    输出

    utils/common.go:6:           IsFoo           100.0%
    utils/logger.go:118:         maskFoo         100.0%
    utils/logger.go:127:         createFoo       100.0%
    utils/logger.go:132:         CreateFakeFoo   100.0%
    utils/foo_validaiton.go:43:  IsFoo           100.0%
    utils/foo_validaiton.go:49:  GreaterThanFoo  100.0%
    utils/yaml.go:39:            closeFOO        100.0%
    total:                       (statements)    100.0%
    

    命令是:

    go tool cover -func=coverage.out | awk 'match($1, /[^\/]+\/[^\/]+$/){$1=substr($1,RSTART,RLENGTH)}1' | column -t
    

    如果您想让模式更具体,以冒号之间的数字结尾,例如 :118:

    /[^\/]+\/[^\/]+:[0-9]+:$/
    

    【讨论】:

      【解决方案3】:

      仅使用awk,您可以:

      awk '$1~/^github\.com/{sub(/^.*utils\//,"utils/"); print; next}1'  file
      

      使用/输出示例

      在文件godata 中使用您的程序输出,您将拥有:

      $ awk '$1~/^github\.com/{sub(/^.*utils\//,"utils/"); print; next}1' godata
      utils/common.go:6:              IsFoo                   100.0%
      utils/logger.go:118:            maskFoo                 100.0%
      utils/logger.go:127:            createFoo               100.0%
      utils/logger.go:132:            CreateFakeFoo           100.0%
      utils/foo_validaiton.go:43:     IsFoo                   100.0%
      utils/foo_validaiton.go:49:     GreaterThanFoo          100.0%
      utils/yaml.go:39:               closeFOO                100.0%
      total:                                             (statements)            100.0%
      

      如果您必须调整最后的total 行使其在列中对齐,那么您可以获得上述记录的记录长度,并从记录中的第一个空格开始删除那么多空格。

      看起来像:

      awk '
          $1~/^github\.com/{
              sub(/^.*utils\//,"utils/")
              l = length($0)
              print
              next
          }
          {
              diff = length($0)-l
              rem = sprintf("%*s", diff, " ")
              sub(rem,"")
              print
          }
      ' file
      

      使用/输出示例

      $ awk '
      >     $1~/^github\.com/{
      >         sub(/^.*utils\//,"utils/")
      >         l = length($0)
      >         print
      >         next
      >     }
      >     {
      >         diff = length($0)-l
      >         rem = sprintf("%*s", diff, " ")
      >         sub(rem,"")
      >         print
      >     }
      > ' godata
      utils/common.go:6:              IsFoo                   100.0%
      utils/logger.go:118:            maskFoo                 100.0%
      utils/logger.go:127:            createFoo               100.0%
      utils/logger.go:132:            CreateFakeFoo           100.0%
      utils/foo_validaiton.go:43:     IsFoo                   100.0%
      utils/foo_validaiton.go:49:     GreaterThanFoo          100.0%
      utils/yaml.go:39:               closeFOO                100.0%
      total:                          (statements)            100.0%
      

      选择您需要的任何一个。

      【讨论】:

        【解决方案4】:

        为了完整起见,一个简单的 awk 解决方案:

        go tool cover -func=coverage.out |
            awk '{ sub(/.*utils/,"utils",$1); print }' |
              column -t
        
        utils/common.go:6:           IsFoo           100.0%
        utils/logger.go:118:         maskFoo         100.0%
        utils/logger.go:127:         createFoo       100.0%
        utils/logger.go:132:         CreateFakeFoo   100.0%
        utils/foo_validaiton.go:43:  IsFoo           100.0%
        utils/foo_validaiton.go:49:  GreaterThanFoo  100.0%
        utils/yaml.go:39:            closeFOO        100.0%
        total:                       (statements)    100.0%
        

        【讨论】:

          【解决方案5】:

          你也可以通过管道传递这个简单的awk

          $ go tool cover -func=coverage.out | awk '{sub(/([^\/]+\/){2}/,"")} 1' | column -t
          

          使用输出数据进行测试:

          awk '{sub(/([^\/]+\/){2}/,"")} 1' file | column -t
          utils/common.go:6:           IsFoo           100.0%
          utils/logger.go:118:         maskFoo         100.0%
          utils/logger.go:127:         createFoo       100.0%
          utils/logger.go:132:         CreateFakeFoo   100.0%
          utils/foo_validaiton.go:43:  IsFoo           100.0%
          utils/foo_validaiton.go:49:  GreaterThanFoo  100.0%
          utils/yaml.go:39:            closeFOO        100.0%
          total:                       (statements)    100.0%
          

          【讨论】:

            【解决方案6】:

            使用您展示的示例,请尝试关注awk 程序。简单的解释是,使用awkmatch 函数匹配正则表达式字符串实用程序,直到下一次出现空格并将其保存到第一个字段并打印已编辑/未编辑的行。

            awk '
            match($1,/utils[^[:space:]]+/){
              $1=substr($1,RSTART,RLENGTH)
            }
            1
            ' Input_file| column -t
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-03-08
              • 2021-11-24
              • 2023-03-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-08
              • 1970-01-01
              相关资源
              最近更新 更多