替换文件中第n次出现之间的所有内容
我有一个包含字段的文件,如下所示:
2|508|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | CPT||0598
2|504|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | CPT||0598
2|505|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise || CPT||0598
2|506|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | |CPT||0598
我想把最终文件归结为:
2|508|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|504|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|505|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|506|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
我尝试了以下方法:
sed 's/|//7'
这很棒,因为它删除了不需要的 | 分隔符,但是,在第 7 个字段中,数据有时在第 7 个字段中有超过 1 个管道,我的代码在第一次运行时没有接收到。
有没有办法用 sed、awk 或 python 来删除一个或多个?在第 7 场使总 | 管道总共只有8个|?
回答
您可以使用
sed 's/|[ |]*//7'
这|[ |]*是匹配的 POSIX BRE 模式
|- 一个管道字符[ |]*- 零个或多个空格或管道字符(您也可以[[:blank:]|]*用来匹配任何水平空白或管道字符)。
请参阅在线演示:
#!/bin/bash
s='2|508|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | CPT||0598
2|504|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | CPT||0598
2|505|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise || CPT||0598
2|506|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise | |CPT||0598'
sed 's/|[ |]*//7' <<< "$s"
输出:
2|508|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|504|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|505|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|506|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|508|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|504|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|505|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
2|506|PNP|20-dec-2015 12:32:20|3451101|0|3xPirate Ship Cruise CPT||0598
如果您需要匹配到第七个管道字符,然后匹配连续的空格和管道并删除所有管道但保留空格,Perl 解决方案可能更合适:
请参阅此在线演示。它的作用是
^(?:[^|]*|){6}[^|]*K|[s|]*匹配六次出现的零个或多个字符|,然后是一个|字符,然后再匹配零个或多个字符而不是管道(with^(?:[^|]*|){6}[^|]*),K省略匹配的文本并|[s|]*匹配并消耗管道字符,然后是任意数量的管道和空白字符- 由于该
e标志,RHS(替换)被视为 Perl 表达式,并且 $&=~s/|//gr意味着g从匹配值中删除所有管道(意味着多次出现)。
- 除非我的眼睛欺骗了我,否则应该保留第 7 个管道两侧的空间,也许是 `sed 's/|[ |]*/ /7' 文件`?