如果字符不遵循指定模式,则将其删除

如果字符不遵循指定模式,则将其删除

我想清理一些文件,并使它们的编写方式更加统一。

所以,我的输入看起来像这样:

$a$h$l)r
^9 ^5 升
\ 乌尔德

问题是,有些空格是“不必要的”,使得比较文件变得困难。因此,我想删除所有空格,除非它们直接跟在以下字符之一之后:

  • $
  • ^
  • 时间
  • iN(N为变量,任意字符1字节长)
  • oN(N 是变量,如上所述)
  • s
  • sN(N 是变量,如上所述)
  • @
  • /
  • =N(N 是变量,如上所述)
  • %N(N 是变量,如上所述)

因此,示例输入可能是:

:
$$$N
$$$a
单反相机
*56 长
氧1氧2
%%xv

想要的输出是:

:
$$$N
$$$a
萨斯利尔
*56升
氧1氧2
%%xv

对于这种%%x v情况,空格被删除,因为它是首字母后面的第三个字符%,其中第二个字符%充当变量。

我正在使用 GNU/Linux 操作系统。

答案1

我想我现在明白了——谢谢

使用扩展的正则表达式来处理额外字符的选项容易一点(请注意,此处使用的示例输入与问题中您自己的输入略有不同):

sed -Ee's|([sio=%]..)?([@!T()^$/].)? *|\1\2|g' \
<<""
:
$ $ $N
$  $  $a
sa  s    l r
*56 l r
o1 o 2
%%xv

:
$ $ $N
$ $ $a
sa s  lr
*56lr
o1 o 2
%%xv

您需要 GNU/BSD/ASTsed才能使用它。等效的 BRE 如下所示:

sed 's|\([soi=%]..\)\{0,1\}\([@!T()^$/].\)\{0,1\} *|\1\2|g'

诀窍是使所有匹配最终都是可选的 - 这样模式的任何部分都不会优先。因为您实际上只是删除数据,而不是插入数据(这必须以不同的方式处理)在匹配目标之间的过渡期间,您不会遇到任何空字符串匹配问题。谁关心删除了多少空字符串?

sed的正则表达式从左到右全局扫描模式空间。如果比赛之间存在重叠的可能性,那么它就不会很好地工作,因为它不会在g全局中回溯。但我能想到的只有一种情况,这里处理。反正右边总是有空间的,左边也总有一些不是空间的。不过,有可能的是可能是您命名的单个字符分隔符之一,但在这种情况下,一个空格仍按应有的方式保留。

当它扫描时,它会根据模式检查输入 - 第一个可能匹配的是 3 字符的,第二个是 2 字符的,第三个是单个 - 空格(尽管这场比赛可能会持续任何时间)

当发现其中任何一个时,sed将用其自身替换前两个匹配中的一个 - 就像逾越节 - 但第三个将被完全删除。并且一口气。

答案2

也许是这样的:

perl -pe 's{((?:[ios=\%].|[\$^T\@!/()])+.)| }{$1}g'

相关内容