【问题标题】:How to keep values from a messy table based on string characteristics如何根据字符串特征保留杂乱表中的值
【发布时间】:2023-04-04 16:43:01
【问题描述】:

我有一个非常困难的 file.asv(值用 @ 分隔),其中包含带有不匹配列的行。

例子:

name@age@city@lat@long
eric@paris@4.4283333333333331e+01@-1.0550000000000000e+02
dan@43@berlin@3.1366000000000000e+01@-1.0371500000000000e+02
london@@2.5250000000000000e+01@1.0538333000000000e+02

纬度和经度值非常一致。它们有 22 或 23 个字符(取决于正号(不存在)和负号),并且始终使用科学记数法。我想只保留每条线的纬度和经度。

预期输出:

lat@long
4.4283333333333331e+01@-1.0550000000000000e+02
3.1366000000000000e+01@-1.0371500000000000e+02
2.5250000000000000e+01@1.0538333000000000e+02

标题不是完全必要的,我可以稍后添加它们。我还可以使用分离的纬度和经度输出,然后将它们粘贴在一起。我可以使用任何 sed 或 awk 命令吗?

【问题讨论】:

标签: string awk sed


【解决方案1】:

使用这个awk

awk 'BEGIN{OFS=FS="@"} {print $(NF-1),$NF}' file

这里,

  • OFS - 输出字段分隔符
  • FS - 输入字段分隔符
  • NF - 字段数

假设latitudelongitude 始终是最后一个字段。 $NF$(NF-1) 将打印最后两个字段。

测试:

$ awk 'BEGIN{OFS=FS="@"} {print $(NF-1),$NF}' file
lat@long
4.4283333333333331e+01@-1.0550000000000000e+02
3.1366000000000000e+01@-1.0371500000000000e+02
2.5250000000000000e+01@1.0538333000000000e+02

【讨论】:

    【解决方案2】:

    假设-o 选项存在,简单的grep 就可以了

    $ grep -o '[^@]*@[^@]*$' file.asv
    lat@long
    4.4283333333333331e+01@-1.0550000000000000e+02
    3.1366000000000000e+01@-1.0371500000000000e+02
    2.5250000000000000e+01@1.0538333000000000e+02
    

    【讨论】:

      【解决方案3】:

      尝试使用正则表达式选择字段

      $ cat ll.awk
      
      function rep(c, n,    ans) { # repeat `c' `n' times
          while (n--) ans = ans c
          return ans
      }
      
      function build_re(  d, s, os) { # build a regexp `r'
          d = "[0-9]" # a digit
          s  = "[+-]" # sign
          os = s "?" # optional sign
      
          r = os d "[.]" rep(d, 16) "e" s d d # adjust here
          r = "^" r "$" # match entire string
      }
      
      function process(   sep, line, i) {
          for (i = 1; i <= NF; i ++ ) {
              if (!($i ~ r)) continue # skip fields
              line = line sep $i; sep = FS
          }
          if (length(line)) print line
      }
      
      BEGIN {
          build_re()
          FS = "@"
      }
      
      { # call on every line of input
          process()
      }
      

      用法:

      $ awk -f ll.awk file.txt 
      4.4283333333333331e+01@-1.0550000000000000e+02
      3.1366000000000000e+01@-1.0371500000000000e+02
      2.5250000000000000e+01@1.0538333000000000e+02
      

      【讨论】:

        【解决方案4】:

        在 Gnu awk 中使用gensub

        $ awk '{print gensub(/(.+)((@[^@]+){2})$/,"\\2","g",$0)}' file
        @lat@long
        @4.4283333333333331e+01@-1.0550000000000000e+02
        @3.1366000000000000e+01@-1.0371500000000000e+02
        @2.5250000000000000e+01@1.0538333000000000e+02
        

        【讨论】:

          猜你喜欢
          • 2020-07-28
          • 1970-01-01
          • 1970-01-01
          • 2021-03-28
          • 2022-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多