替换文件中第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' 文件`?

以上是替换文件中第n次出现之间的所有内容的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>