我希望在字符('_')前面的所有地方用大写字母替换带有连字符的下划线,后跟大写字母,例如QWQW_IOIO,OP_FD_GF_JK,TRT_JKJ等。在一份文件中需要更换。
我试图用vim替换它:
:%s/[A-Z]_[A-Z]/[A-Z]-[A-Z]/g
但这导致QWQW_IOIO
与QWQ[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 '-'
答案 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
与以前相同的问题,现在只有一个字母而不是多个字母。