【问题标题】:Grep / search for a string in a csv, then parse that line and do another grepgrep / 在 csv 中搜索一个字符串,然后解析该行并执行另一个 grep
【发布时间】:2015-02-01 10:02:52
【问题描述】:

标题的措辞可能不太好,但我目前需要编写一个搜索脚本,在 CSV 中找到给定的字符串,然后解析找到的行并使用该行中的元素执行另一个 grep。

例子:

KEY1,TRACKINGKEY1,TRACKINGNUMBER1-1,PACKAGENUM1-1
    ,TRACKINGKEY1,TRACKINGNUMBER1-2,PACKAGENUM1-2
    ,TRACKINGKEY1,TRACKINGNUMBER1-3,PACKAGENUM1-3
    ,TRACKINGKEY1,TRACKINGNUMBER1-4,PACKAGENUM1-4
    ,TRACKINGKEY1,TRACKINGNUMBER1-5,PACKAGENUM1-5
KEY2,TRACKINGKEY2,TRACKINGNUMBER2-1,PACKAGENUM2-1
KEY3,TRACKINGKEY3,TRACKINGNUMBER3-1,PACKAGENUM3-1
    ,TRACKINGKEY3,TRACKINGNUMBER3-2,PACKAGENUM3-2

我需要做的是 grep 给定键的 .csv 文件 [在本例中为 key1],然后抓取 TRACKINGKEY1 以便我可以 grep 剩余的行。我们的运输软件不会在每一行都输出packingslip key,这就是为什么我必须先按KEY搜索,然后按TRACKINGKEY才能得到所有的tracking number。

所以最初使用 KEY1 我最终想为自己输出一个漂亮的小字符串,例如“TRACKINGNUMBER1-1;TRACKINGNUMBER1-2;TRACKINGNUMBER1-3;TRACKINGNUMBER1-4;TRACKINGNUMBER1-5”

【问题讨论】:

  • 跟踪号中的第一个数字似乎与密钥有关?

标签: linux parsing csv sed grep


【解决方案1】:
awk '/KEY1/ {print $3}' FS=,

结果

TRACKINGNUMBER1-1
TRACKINGNUMBER1-2
TRACKINGNUMBER1-3
TRACKINGNUMBER1-4
TRACKINGNUMBER1-5

【讨论】:

    【解决方案2】:
    $ awk -v key=KEY1 -F, '$1==key{f=1} ($1!~/^ *$/)&&($1!=key){f=0} f{print $3}' file
    TRACKINGNUMBER1-1
    TRACKINGNUMBER1-2
    TRACKINGNUMBER1-3
    TRACKINGNUMBER1-4
    TRACKINGNUMBER1-5
    

    glennjackman 很有帮助地指出,通过为 FS 使用“更智能”的值,内部逻辑可以更简单。

    awk -v key=KEY1 -F' *,' '$1==key{f=1} $1 && $1!=key{f=0} f{print $3}' file
    

    -v key=KEY1将值KEY1赋给awk变量key

    -F' *,' 将值 *,(这是一个正则表达式)分配给 awk FS 变量(控制字段拆分)

    $1==key{f=1} 如果该行的第一个键等于key 变量(KEY1)的值,则将值1 分配给变量f(找到我们想要的第一个键行)

    $1 && $1!=key{f=0} 如果第一个字段具有真值(在 awk 中为非零、非空字符串)并且第一个字段的值不等于 key 变量的值,则分配将 0 的值赋值给变量 f(找到我们的无密钥行的结尾)

    f{print $3} 如果变量f 具有真值(记住非零、非空字符串),则打印该行的第三个字段

    【讨论】:

    • 如果你使用-F' *,'会简单一点,那么你就有$1 && $1!=key
    • @glennjackman 很好。我的初始版本使用了该测试,我花了一分钟才弄清楚为什么它不起作用,但我没想到修改 FS 来修复它。
    • 哇,这真的证明了我是个十足的菜鸟,因为这在我看来完全是胡言乱语。 :) 有人愿意向我解释吗?
    • 一项改进,假设所有行都按键分组:而不是{f=0} 使用{exit}
    • @glennjackman 想到了。不确定是否一定会如此(尽管我认为也是如此),所以采取了更安全的路线。但很高兴指出。
    【解决方案3】:

    再来一个 awk

    awk -F, '/KEY1/,/KEY/{print $3}' file
    

    或给定样本数据

    awk 'match($0,/([^,]+NUMBER1[^,]+)/,a){print a[0]}'
    

    甚至

    awk -F, '$3~/NUMBER1/&&$0=$3' file
    

    【讨论】:

      【解决方案4】:
      $ sed -nr '/^KEY1/, /^KEY/ { /^(KEY1| )/!d; s/.*(TRACKINGNUMBER[^,]+).*/\1/ p}' input
      TRACKINGNUMBER1-1
      TRACKINGNUMBER1-2
      TRACKINGNUMBER1-3
      TRACKINGNUMBER1-4
      TRACKINGNUMBER1-5
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-25
        • 2013-05-17
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多