如何在sed正则表达式分组中匹配包含扩展ASCII的所有字符?
解决sed正则匹配扩展ASCII字符的问题
问题根源
sed默认的正则行为受系统locale影响:
- 正则中的
.默认只匹配ASCII可打印字符(0x20-0x7E),扩展ASCII(如0xA5这类)不在匹配范围内,导致你的分组(.{12})无法正确包含扩展ASCII字符,命令失效。 - 字符范围
[\xa0-\xfe]在非Clocale下,会按locale的字符排序规则解析,而非字节值顺序,所以无法正确匹配目标扩展ASCII字符,甚至出现删除字符的异常情况。
解决方案1:强制使用C locale执行sed
C locale会让sed按原始字节处理字符,此时:
.会匹配除换行外的所有字节(包括扩展ASCII)- 字符范围会严格按字节值大小解析
修复场景2的命令
执行时加上LC_ALL=C前缀:
echo -e "TO BE REMOVED. THIS\xa5NOT. TO BE REMOVED" | LC_ALL=C sed -E 's/(TO BE REMOVED)(.{12})(.*)/IT WAS REMOVED\2/g'
执行后会得到预期结果:IT WAS REMOVED. THIS¥NOT.(注:0xA5对应字符¥)
修复场景4的命令
同样添加LC_ALL=C:
echo -e "HI FRIEND, \xa5 ARE YOU?" | LC_ALL=C sed -E 's/[\xa0-\xfe]/HOW/g'
执行后会得到正确结果:HI FRIEND, HOW ARE YOU?
解决方案2:用[^\n]代替.
如果不想修改locale,也可以用[^\n]匹配所有非换行字符(包括扩展ASCII),比如场景2的命令可改写为:
echo -e "TO BE REMOVED. THIS\xa5NOT. TO BE REMOVED" | sed -E 's/(TO BE REMOVED)([^\n]{12})(.*)/IT WAS REMOVED\2/g'
这个写法不受locale影响,同样能匹配扩展ASCII字符。
内容的提问来源于stack exchange,提问作者Shorosky
相关产品推荐
相关产品推荐

