删除 2 个已知字符串之间的字符

删除 2 个已知字符串之间的字符

我有一个如下数据集:

\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss

我的要求:我想删除START 和 END 之间所有出现的反斜杠\和双引号。"

期望的输出:

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

笔记:

  1. 同一行有多个 START/END
  2. 我只想删除START 和 END 之间的\and ",而不是其他地方
  3. 我的文件有多行(类似于上面显示的行)
  4. sed我只需要使用

我尝试了如下所示的方法(试图"先单独摆脱),但它没有给我想要的结果:

sed '/START/,/END/ s/"//g'

答案1

`假设文件中没有字符。如果您只是将下面的行全部更改`为任何其他字符,那么这些字符肯定不会出现在输入中。

sed -e 's/END/`/g;:X' -e 's/\(START[^`]*\)["\]/\1/g;tX' -e 's/`/END/g'

答案2

其实这并不难sed。您始终可以使用\newline分隔一个部分或者\n您可以暂时将分隔符换成ewline。你可以不用循环来做到这一点:

sed 's/$/START/;s/END/&
/g;  y/D\n/\nD/
     s/\([^D]*START\)*[D\"]*/\1/g
     y/\n/D/;s/.....$//
' <<\IN                                           
\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss
IN

有时你只需要以不同的方式思考问题即可。与其删除所有之间\\"的内容STARTEND不如将问题转向如何保存\\"仅当它们出现在行首和字符串以及行的最后一个和尾部之间时,STARTSTART会变END得更END容易一些(如果,诚然,直觉上不是这样的话)。这是因为sed处理*零个或多个匹配的方式g局部s///替代语境。

虽然从头到第一个START位会作为其余部分的自然结果而被清除,但最后END到尾的位却不会 - 因此我们需要在行START尾附加另一个位。获得额外的内容后,START我们会\n在每次出现 时附加一个 ewline 字符END。然后使用y///音译命令,我们同时将所有D字符换成\newlines,反之亦然。顺便说一句,音译命令y///在这里不仅非常方便,而且比s///替换命令更有效。

此时,l我们的模式空间将打印:

\\"XXX \\ START sapiodj \\\\" aj \\d 2387 EN\nD hddo\\" START bbcc  \\\\" EN\nD ssSTART$

正如您所看到的,现在所有\\"需要保存的字符都正好位于行首或 aD和字符串之间,并且它们之间START没有s。D因此,删除不需要的字符(包括我们额外的 s)的g全局替换也替换了需要自行保存的字符。最后我们只需要再次交换和s 并删除最后一个。s///D\nDSTART

通过这种方式,您可以可靠地分隔字段sed 无论输入并且您不需要依赖任何不出现的字符,而是保证永远不会出现在一行上的字符 -\n当然,这就是 ewline 字符。

完成后打印:

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

答案3

sed

sed 's/:/::/g;s/</:l/g;s/>/:g/g; # escape :, <, >
     s/START/&</g; s/END/>&/g;   # replace START/END with <>
     :1
     s/\(<[^>]*\)[\"]/\1/g;t1
     s/[<>]//g;s/:g/>/g;s/:l/</g;s/::/:/g; # restore <>:'

perl

perl -pe's|START.*?END|$&=~y/\\"//rd|ge'

答案4

你有在评论中指出awk也是允许的。所以我的回答就是基于此。

假设您的STARTs 和ENDs 是平衡的,如果您在任一单词上拆分行,您会发现您想要从所有偶数字段中删除反斜杠和双引号。为此:

awk -F 'START|END' '{
                      for(i=2;i<=NF;i+=2){ # For each even-numbered field
                        gsub(/["\\]/,"",$i) # Remove " and \ from it
                        $i="START"$i"END" # Put START and END back around it
                      }
                    }' your_file

这假设您的实现awk具有gsub我无法保证的功能。

作为旁注,您的sed不起作用,因为它基本上是说“将替换应用于以行匹配开头START并以行匹配结尾的行范围END”。

相关内容