如何在sed中访问匹配位置(&)后的字符?解决文本连字符替换问题
在sed中匹配字母数字后的连字符并添加空格的正确方法
我来帮你搞定这个sed的问题!你当前遇到的问题是因为命令的匹配逻辑不对,导致把字母和连字符分开了,咱们一步步来修正。
首先说下你当前命令的问题:sed -E 's/[[:alnum:]]-($|[^[:alnum:]])/ &/g' 之所以会输出 - h i- 1 2-,是因为它匹配的是单个字母数字+连字符+非字母数字/行尾,然后在整个匹配串前面加空格——相当于把i- 变成了i-,前面的h就被单独拆出来了,完全偏离了你的需求。
那正确的思路应该是:咱们要找的是「前面是字母数字、后面不是字母数字(或行尾)的连字符」,同时要跳过像multi-line这种连字符前后都是字母数字的情况。虽然POSIX sed不支持正向先行断言,但用捕获分组就能完美解决这个问题。
试试这个命令:
echo " - hi- 12- multi-line" | sed -E 's/([[:alnum:]])-([^[:alnum:]]|$)/\1- \2/g'
我给你拆解下这个命令的逻辑:
([[:alnum:]]):捕获第一个分组,抓连字符前面的那个字母数字字符-:精准匹配我们要处理的连字符([^[:alnum:]]|$):捕获第二个分组,匹配连字符后面的非字母数字字符,或者行尾(这一步就是为了跳过multi-line这种连字符后还是字母的情况)- 替换成
\1- \2:把捕获的内容重新组合,在连字符和第二个分组的内容之间加个空格,也就是变成「字母数字- 后续内容」
测试一下效果:
输入: - hi- 12- multi-line
输出: - hi - 12 - multi-line
完全符合你的要求:
- 开头的
-前面是空格,不会被修改 hi-和12-都正确变成了hi -和12 -multi-line因为连字符后面是字母l,不会被匹配到,所以保持原样
如果你的环境里sed支持扩展正则(大部分现代Linux/macOS的sed都支持,-E就是开启扩展正则的参数),这个命令就能正常工作啦。
内容的提问来源于stack exchange,提问作者d9ngle
相关产品推荐
相关产品推荐

