Vim或sed:替换模式中的字符

时间:2017-07-12 19:22:16

标签: vim sed replace

我希望在字符('_')前面的所有地方用大写字母替换带有连字符的下划线,后跟大写字母,例如QWQW_IOIO,OP_FD_GF_JK,TRT_JKJ等。在一份文件中需要更换。

我试图用vim替换它: :%s/[A-Z]_[A-Z]/[A-Z]-[A-Z]/g 但这导致QWQW_IOIOQWQ[A-Z]-[A-Z]OIO :(

我尝试使用sed命令: sed -i '/[A-Z]_[A-Z]/ s/_/-/g' ./file_name 这导致了整条生产线的更换。 e.g。

QWQW_IOIO variable may contain '_' or '-'行被

取代

QWQW-IOIO variable may contain '-' or '-'

2 个答案:

答案 0 :(得分:5)

你对第一个vim方法有正确的想法。但是您需要使用捕获组来记住[A-Z]部分中找到的字符。这些很好地解释了here:h /\1下。作为旁注,我建议使用\u代替[A-Z],因为它既短又快。这意味着您想要的解决方案是:

:%s/\(\u\)_\(\u\)/\1-\2/g

或者,如果您想使用魔术设置使其更具可读性:

:%s/\v(\u)_(\u)/\1-\2/g

另一种选择是限制被\zs\ze原子取代的搜索部分:

:%s/\u\zs_\ze\u/-/g

这是我所知道的最短的解决方案。

答案 1 :(得分:2)

这应该做你想要的,假设GNU sed。

sed -i -r -e 's/([A-Z]+)_([A-Z]+)/\1-\2/g' ./file_name

说明:

-r标志启用扩展正则表达式

[A-Z]+是"一个或多个大写字母"

()将模式组合在一起并创建编号的记忆匹配

\1\2将这些记忆中的比赛放入替补。

所以基本上这会找到一大块大写字母后跟一个下划线,然后是另一大块大写字母,只记住字母块为2组,

([A-Z]+)_([A-Z]+)

然后它重播这些组,但在两者之间用连字符代替下划线。

\1-\2

最后的g标志表示即使模式在一行上多次出现也会这样做。

请注意,在这种情况下,这会有所不同:

QWQW_IOIO_ABAB

因为它第一次匹配,而不是第二次匹配;第二部分没有匹配,因为第一场比赛消耗了IOIO。这样会导致

QWQW-IOIO_ABAB

此版本删除了+,因此它只匹配一个大写字母,并且不会以同样的方式中断:

sed -i -r -e 's/([A-Z])_([A-Z])/\1-\2/g'

如果你有这样的字符串,它仍然有一个小缺陷:

A_B_C

与以前相同的问题,现在只有一个字母而不是多个字母。

相关问题