Vim Regex 捕获组[ bau-> byau: ceu-> cyeu ]

我有一份单词清单:

bau
ceu
diu
fou
gau

我想把这个清单变成:

byau
cyeu
dyiu
fyou
gyau

我没有成功地尝试了下面的命令:

:%s/(\w)(\w\w)/\1y\2/g

既然这不起作用,那么我需要做些什么更改才能使正则表达式捕获组在 Vim 中工作呢?

127978 次浏览

解决这个问题的一种方法是确保模式由 逃跑了括号括起来:

:%s/\(\w\)\(\w\w\)/\1y\2/g

略短(和更多的 魔法-al)是使用 \v,这意味着在模式后面的所有 ASCII 字符,除了 '0'-'9''a'-'z''A'-'Z''_'有一个特殊的含义:

:%s/\v(\w)(\w\w)/\1y\2/g

参见:

你还必须摆脱群体偏见:

:%s/\(\w\)\(\w\w\)/\1y\2/g

这样就行了。

如果你不想用反斜杠转义捕获组(这就是你错过的) ,在 \v前面加上 \v,将 Vim 的正则表达式引擎转换成 非常神奇模式:

:%s/\v(\w)(\w\w)/\1y\2/g

你也可以使用这个短一些的图案:

:%s/^./&y
  • %s将该模式应用于整个文件。
  • ^.匹配该行的第一个字符。
  • &y在模式之后添加 y

Vim中,在 选择上,如下

:'<,'>s/^\(\w\+ - \w\+\).*/\1/

或者

:'<,'>s/\v^(\w+ - \w+).*/\1/

解析

Space - Commercial - Boeing

Space - Commercial

同样地,

apple - banana - cake - donuts - eggs

被解析为

apple - banana

解释

  • 比赛起跑线
  • 根据第一个正则表达式(已接受的答案) ,或者用 \v(@ingo-karkat 的答案)作为前缀,转义 (+)
  • \w\+查找一个单词(\w将查找第一个 性格) : 在本例中,我搜索一个单词后跟 -,后跟另一个单词)
  • 在捕获组之后,需要 .*来查找/匹配/排除剩余的文本

附录。这有点偏离主题,但我认为 Vim 不太适合执行更复杂的正则表达式/捕获。[我正在做类似于下面的事情,这就是我如何发现这个帖子的。]

在这些情况下,最好将行转储到一个文本文件并“就地”编辑它

sed -i ...

或者重新定向

sed ... > out.txt

在终端(或 BASH 脚本中,...) :


echo 'Space Sciences - Private Industry - Boeing' | sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/'


Space Sciences - Private Industry


cat in.txt


Space Sciences - Private Industry - Boeing


sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/' ~/in.txt > ~/out.txt


cat ~/out.txt


Space Sciences - Private Industry


## Caution: if you forget the > redirect, you'll edit your source.
## Subsequent > redirects also overwrite the output; use >> to append
## subsequent iterations to the output (preserving the previous output).
 

## To edit "in place" (`-i` argument/flag):


sed -i -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/' ~/in.txt


cat in.txt


Space Sciences - Private Industry

sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/'

(注意 {1,2})允许灵活地查找单词的 {x,y}重复——参见 https://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html

在这里,由于我的短语是由 -分隔的,我可以简单地调整这些参数来得到我想要的。