160

我有一个单词列表:

bau
ceu
diu
fou
gau

我想把这个列表变成:

byau
cyeu
dyiu
fyou
gyau

我没有成功尝试命令:

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

鉴于这不起作用,我必须改变什么才能使正则表达式捕获组在 Vim 中工作?

4

5 回答 5

268

解决此问题的一种方法是确保模式被转义括号括起来:

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

稍微短一点(而且更神奇的 -al)是使用\v,这意味着在它之后的所有 ASCII 字符除了'0'-'9',和'a'-'z'之外都有特殊含义:'A'-'Z''_'

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

看:

于 2013-11-11T08:46:02.600 回答
50

如果您不想用反斜杠转义捕获组(这是您错过的),请预先\v将 Vim 的正则表达式引擎转换为非常神奇的模式:

:%s/\v(\w)(\w\w)/\1y\2/g
于 2013-11-11T08:47:38.607 回答
44

你也可以使用这个更短的模式:

:%s/^./&y
  • %s将模式应用于整个文件。
  • ^.匹配行的第一个字符。
  • &y在模式之后添加y
于 2015-05-28T15:38:49.727 回答
17

您还必须转义 Grouping 括号:

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

这就是诀窍。

于 2013-11-11T08:46:03.087 回答
2

非常好!在selection上,使用以下内容(例如):

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

或者

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

解析Space - Commercial - BoeingSpace - Commercial.

解释:

  • ^: 匹配行首
  • \-escape (, +,)根据第一个正则表达式(接受的答案) - 或前面加上\v(@ingo-karkat 的答案)
  • \w\+找到一个词(\w将找到第一个字符):在这个例子中,我搜索一个词,-然后是另一个词)
  • .*捕获组之后需要查找/匹配/排除剩余文本

附录。 这有点离题,但我建议 Vim 不适合执行更复杂的正则表达式/捕获。[我正在做类似于以下的事情,这就是我找到这个线程的方式。]

在这些情况下,最好将这些行转储到文本文件并“就地”(sed -i ...)或重定向(sed ... > out.txt)编辑它。

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

touch ~/in.txt
touch ~/out.txt

echo 'Space Sciences - Private Industry - Boeing' > ~/in.txt
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.

## source unaltered:
cat in.txt
Space Sciences - Private Industry - Boeing

## edit in place:
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/'允许灵活地查找{x,y}单词的重复 - 请参阅https://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html。在这里,由于我的短语用 分隔-,我可以简单地调整这些参数以获得我想要的。

于 2021-03-24T19:33:46.873 回答