替换文件中第 n 次出现之间的所有内容

Roc*_*ost 1 python awk sed

我有一个包含字段的文件,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

我想把最终文件归结为:

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
Run Code Online (Sandbox Code Playgroud)

我尝试了以下方法:

sed 's/|//7'
Run Code Online (Sandbox Code Playgroud)

这很棒,因为它删除了不需要的 | 分隔符,但是,在第 7 个字段中,数据有时在第 7 个字段中有超过 1 个管道,我的代码在第一次运行时没有接收到。

有没有办法用 sed、awk 或 python 来删除一个或多个?在第 7 场使总 | 管道总共只有8个|?

Wik*_*żew 6

您可以使用

sed 's/|[ |]*//7'
Run Code Online (Sandbox Code Playgroud)

|[ |]*是匹配的 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"
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

如果您需要匹配到第七个管道字符,然后匹配连续的空格和管道并删除所有管道但保留空格,Perl 解决方案可能更合适:

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
Run Code Online (Sandbox Code Playgroud)

请参阅此在线演示。它的作用是

  • ^(?:[^|]*\|){6}[^|]*\K\|[\s|]*匹配六次出现的零个或多个字符|,然后是一个|字符,然后再匹配零个或多个字符而不是管道(with ^(?:[^|]*\|){6}[^|]*),\K省略匹配的文本并\|[\s|]*匹配并消耗管道字符,然后是任意数量的管道和空白字符
  • 由于该e标志,RHS(替换)被视为 Perl 表达式,并且
  • $&=~s/\|//gr意味着g从匹配值中删除所有管道(意味着多次出现)。

  • 除非我的眼睛欺骗了我,否则应该保留第 7 个管道两侧的空间,也许是 `sed 's/|[ |]*/ /7' 文件`? (2认同)