如何删除每个跟在另一个单词后面的单词,而不改变空格?

如何删除每个跟在另一个单词后面的单词,而不改变空格?

假设我的文件如下所示:

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 实现这一点?

答案1

好的,我找到了如何做到这一点的方法。使用 sed 执行此操作的命令如下:

sed -i -E 's/foo([[:blank:]]*)bar/\1bar/' file

答案2

对于支持 perl 兼容正则表达式 (PCRE) 的任何内容,您都可以使用正向前瞻:

perl -pe 's/foo(?=\s*bar)//' < txt

(?=)是“零宽度正向前瞻断言“。

它需要匹配整个 RE 才能匹配,但它不包括它匹配的内容,所以您不需要捕获并重新插入匹配的文本。

此外,还有负向前瞻,以及正向和负向后瞻,统称为“环视”。

答案3

使用拉库(以前称为 Perl_6)

~$ raku -pe 's:g/   foo <?before \s* bar> //;'   file

#OR

~$ raku -pe 's:g/ <(foo)>        \s* bar //;'  file

上述答案是用 Raku 编写的,Raku 是 Perl 系列编程语言的成员之一。Raku 的优势包括内置的高级 Unicode 支持,以及强大/精炼的正则表达式实现。上面,Raku 正则表达式在识别域(的左半部分s///)中具有空格容忍性,因此正则表达式原子可以展开(并排列)。此外,所有正则表达式修饰符:global(例如 或:g)都移至 Raku 中的运算符头部s///。与 Perl 一样,全局标志或“副词”允许每行有多个匹配项。

第一个答案是 @jcaron 出色的 Perl(5) 答案的粗略翻译。请注意,在 Raku 中,正向前瞻拼写为<?before ... >。第二个答案使用 Raku 的<(...)>捕获标记,因此在所有三个原子匹配后,仅foo在捕获中保留 (并在替换中删除)。

这两个答案都特别改变了foobar中间只有空格。这是一个重要的点:给定短语“my valentine, my bloody valentine”,Raku 代码s:g/my <?before \s* valentine> //将删除第一个“my”(因为“my-之前-valentine),但第二个“my”保持不变。

https://docs.raku.org/language/regexes
https://raku.org

相关内容