假设我的文件如下所示:
foo bar
foo bar bar
foo foo bar foo
我想要做的是删除foo
后面跟着 a 的每个bar
(即它们之间只有空格),而不更改任何空格。在下面,我用下划线替换了所有应该删除的字符,以明确这一点:
___ bar
___ bar bar
foo ___ bar foo
该命令应生成以下文件:
bar
bar bar
foo bar foo
我怎样才能用 sed 或 awk 实现这一点?
好的,我知道如何做到这一点。使用 sed 执行此操作的命令是:
对于任何支持 perl 兼容正则表达式 (PCRE) 的东西,您可以使用正向前瞻:
(?=)
是一个“零宽度正向先行断言”。它需要匹配整个 RE 才能匹配,但它不包括它匹配的内容,因此您不需要捕获并重新插入匹配的文本。
还有消极的前瞻、积极和消极的后瞻,统称为“lookarounds”。
使用Raku(以前称为 Perl_6)
上面的答案是用 Raku 编码的,Raku 是 Perl 编程语言家族的成员。Raku 的优点包括内置高级 Unicode 支持,以及强大/精致的正则表达式实现。上图,Raku 正则表达式在识别域( 的左半部分)中可以容忍空格
s///
,因此正则表达式原子可以展开(并排列)。此外,所有正则表达式修饰符(例如:global
(或:g
))都会移动到 Raku 中运算符的开头s///
。与 Perl 一样,全局标志或“副词”允许每行有多个匹配项。第一个答案是@jcaron 优秀的 Perl(5) 答案的粗略翻译。请注意,在 Raku 中,正向前瞻拼写为
<?before ... >
。第二个答案使用 Raku 的<(
...)>
捕获标记,以便在所有三个原子匹配后,仅foo
保留在捕获中(并在替换中删除)。这两个答案
foo
之前都发生了特别的变化bar
,中间只有空格。这是很重要的一点:给定短语“my valentine, my Bloody valentine”,Raku 代码s:g/my <?before \s* valentine> //
将删除第一个“my”(因为“my- is_before -valentine”),但第二个“my”保持不变。https://docs.raku.org/language/regexes
https://raku.org