【问题标题】:Adding regex match found in column to last column将列中找到的正则表达式匹配添加到最后一列
【发布时间】:2021-03-25 21:11:03
【问题描述】:

在 bash 中使用 perl、sed 或 awk,我需要在 csv 第 3 列中找到正则表达式模式并将其添加到最后第 4 列。

例如转这个:

2020/10/26,249.00,Test10028
2020/10/24,569.00,Test 00074
2020/10/24,1999.00,0016 1708fqb8ba
2020/10/24,1399.00,00450 165058hb1bda
2020/10/23,399.00,Att-10170 158bb8ba
2020/10/22,599.00,Ref:10150 1605fk0bsf
2020/10/22,5669.00,1605fk0bsf

进入这个:

2020/10/26,249.00,Test10028,10028
2020/10/24,569.00,Test 00074,00074
2020/10/24,1999.00,0016 1708fqb8ba,0016
2020/10/24,1399.00,00450 165058hb1bda,00450
2020/10/23,399.00,Att-10170 158bb8ba,10170
2020/10/22,599.00,Ref:10150 1605fk0bsf,10150
2020/10/22,5669.00,1605fk0bsf,

我发现的 PCRE 正则表达式过滤了我需要的内容(只有数字,长度 4-5,以 0-1 开头,没有尾词。):

(?<!\d)[0-1]\d{3,4}(?!\w)

在 akw 或 sed 中使用它不起作用。我试过的一些代码:

awk -F, 'match($3, /(?<!\d)[0-1]\d{3,4}(?!\d)/, a) {print a[0]","$4 }' file.csv
sed -re 's/(?<!\d)[0-1]\d{3,4}(?!\d)/g' file.csv

但是 perl 确实给了我使用的结果:

perl -pe 's/(?<!\d)[0-1]\d{3,4}(?!\w)/!!!!/g' file.csv
2020/10/26,249.00,Test!!!!
2020/10/24,569.00,Test !!!!
2020/10/24,!!!!.00,!!!! 1708fqb8ba
2020/10/24,!!!!.00,!!!! 165058hb1bda
2020/10/23,399.00,Att-!!!! 158bb8ba
2020/10/22,599.00,Ref:!!!! 1605fk0bs

【问题讨论】:

  • awk 和 sed 不支持 pcre。
  • 在您的预期结果中,2020/10/22,5669.00,1605fk0bsf, 可以吗?不应该是2020/10/22,5669.00,1605fk0bsf,1605吗?
  • @WiktorStribiżew 没有结尾词,他说。
  • 不,不应该接受任何尾随词。
  • 这意味着,没有字母粘在要提取的数字上。但是为什么在1605fk0bsf后面加上逗号,如果不应该匹配呢?

标签: regex csv perl awk sed


【解决方案1】:

我们可以使用-F, -a 来引发@F = split /,/ 以便使用第三个字段并创建第四个。

perl -F, -pale'($F[3]) = $F[2] =~ /(?<!\d)([0-1]\d{3,4})(?!\w)/; $_=join(",", @F)'

【讨论】:

    【解决方案2】:

    你可以使用这个 GNU awk:

    rx='([^0-9]|^)([01][0-9]{3,4})([^[:alnum:],][^,]*)?$'
    awk -v r=$rx 'BEGIN{FS=OFS=","} {print ($3 ~ r) ? $0 OFS gensub(r, "\\1\\2\\3,\\2", 1, $3) : $0 OFS}' file.csv > newfile.csv
    

    请参阅online sed demo(和regex demo)。

    详情

    • ([^0-9]|^) - 第 1 组:任何非数字字符或字符串开头
    • ([01][0-9]{3,4}) - 第 2 组:01,然后是三位或四位数字
    • ([^[:alnum:],][^,]*) - 除数字、字母和逗号外的字符的可选序列,然后是除逗号外的零个或多个字符。
    • $ - 字符串结束。
    • \1\2\3,\2 - 替换是第 1、2、3 组、逗号和第 2 组值的串联。

    awk 命令:

    • -v r=$rx - 将正则表达式 $rx 作为变量 r 传递给 awk 脚本
    • BEGIN{FS=OFS=","} - 将输入和输出字段分隔符设置为逗号
    • {print ($3 ~ r) ? $0 OFS gensub(r, "\\1\\2\\3,\\2", 1, $3) : $0 OFS} - 如果正则表达式匹配字段 3,则 gensub 的结果将在逗号后附加到整行(记录),否则仅附加逗号
    • gensub(r, "\\1\\2\\3,\\2", 1, $3) 替换字段 3 中第一次出现的模式。

    【讨论】:

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