将在列中找到的正则表达式匹配添加到最后一列
Adding regex match found in column to last column
在 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(, /(?<!\d)[0-1]\d{3,4}(?!\d)/, a) {print a[0]"," }' 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
我们可以使用 -F, -a
引起 @F = split /,/
以便与第三个字段一起使用并创建第四个字段。
perl -F, -pale'($F[3]) = $F[2] =~ /(?<!\d)([0-1]\d{3,4})(?!\w)/; $_=join(",", @F)'
你可以使用这个 GNU awk:
rx='([^0-9]|^)([01][0-9]{3,4})([^[:alnum:],][^,]*)?$'
awk -v r=$rx 'BEGIN{FS=OFS=","} {print ( ~ r) ? [=10=] OFS gensub(r, "\1\2\3,\2", 1, ) : [=10=] OFS}' file.csv > newfile.csv
参见 online sed
demo (and the regex demo)。
详情
([^0-9]|^)
- 第 1 组:任何非数字字符或字符串开头
([01][0-9]{3,4})
- 第 2 组:0
或 1
,然后是三位或四位数字
([^[:alnum:],][^,]*)
- 数字、字母和逗号以外的字符的可选序列,然后是逗号以外的零个或多个字符。
$
- 字符串结尾。
,
- 替换是组 1、2、3、逗号和组 2 值的串联。
awk
命令:
-v r=$rx
- 将正则表达式 $rx
作为变量 r
传递给 awk 脚本
BEGIN{FS=OFS=","}
- 将输入和输出字段分隔符设置为逗号
{print ( ~ r) ? [=24=] OFS gensub(r, "\1\2\3,\2", 1, ) : [=24=] OFS}
- 如果正则表达式匹配字段 3,gensub
的结果将附加到整行(记录)的逗号之后,否则仅附加逗号
gensub(r, "\1\2\3,\2", 1, )
替换字段 3 中第一次出现的模式。
您不需要 gnu-awk 即可完成。它在正则表达式中有点冗长,但它完成了工作:
nice gcat test.csv \
\
| mawk2 'BEGIN { FS=OFS=","
} ((~/^[^0-9]*[0-1][0-9] \
[0-9][0-9][0-9]?($|[^[:alpha:]])/) && \
\
(($++NF=)+gsub(/^[^0-9]*|[ ].*$/,"",$NF))) || 1'
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
这纯粹是假设输入是干净的,并且不会在应用过滤器之前尝试执行任何类型的数据清理。
在 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(, /(?<!\d)[0-1]\d{3,4}(?!\d)/, a) {print a[0]"," }' 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
我们可以使用 -F, -a
引起 @F = split /,/
以便与第三个字段一起使用并创建第四个字段。
perl -F, -pale'($F[3]) = $F[2] =~ /(?<!\d)([0-1]\d{3,4})(?!\w)/; $_=join(",", @F)'
你可以使用这个 GNU awk:
rx='([^0-9]|^)([01][0-9]{3,4})([^[:alnum:],][^,]*)?$'
awk -v r=$rx 'BEGIN{FS=OFS=","} {print ( ~ r) ? [=10=] OFS gensub(r, "\1\2\3,\2", 1, ) : [=10=] OFS}' file.csv > newfile.csv
参见 online sed
demo (and the regex demo)。
详情
([^0-9]|^)
- 第 1 组:任何非数字字符或字符串开头([01][0-9]{3,4})
- 第 2 组:0
或1
,然后是三位或四位数字([^[:alnum:],][^,]*)
- 数字、字母和逗号以外的字符的可选序列,然后是逗号以外的零个或多个字符。$
- 字符串结尾。,
- 替换是组 1、2、3、逗号和组 2 值的串联。
awk
命令:
-v r=$rx
- 将正则表达式$rx
作为变量r
传递给 awk 脚本BEGIN{FS=OFS=","}
- 将输入和输出字段分隔符设置为逗号{print ( ~ r) ? [=24=] OFS gensub(r, "\1\2\3,\2", 1, ) : [=24=] OFS}
- 如果正则表达式匹配字段 3,gensub
的结果将附加到整行(记录)的逗号之后,否则仅附加逗号gensub(r, "\1\2\3,\2", 1, )
替换字段 3 中第一次出现的模式。
您不需要 gnu-awk 即可完成。它在正则表达式中有点冗长,但它完成了工作:
nice gcat test.csv \
\
| mawk2 'BEGIN { FS=OFS=","
} ((~/^[^0-9]*[0-1][0-9] \
[0-9][0-9][0-9]?($|[^[:alpha:]])/) && \
\
(($++NF=)+gsub(/^[^0-9]*|[ ].*$/,"",$NF))) || 1'
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
这纯粹是假设输入是干净的,并且不会在应用过滤器之前尝试执行任何类型的数据清理。