如何在旧版BSD awk中匹配首个POSIX [:cntrl:]控制字符?
问题根源与解决方案
问题原因
旧版BSD awk(如FreeBSD 10及更早版本、早期macOS自带的awk)对POSIX字符类[:cntrl:]的实现不符合标准,错误地将非控制字符(如空格,甚至部分可打印字符)纳入匹配范围,或是在非C locale环境下字符类解析异常,导致错误匹配了字符串开头的字符,返回了错误的RSTART值。
解决方案
方案1:使用明确的ASCII控制字符范围代替POSIX字符类
直接用正则[\x00-\x1F\x7F]匹配所有ASCII控制字符(ASCII码0-31和127),这个写法在新旧awk中行为一致,不会受实现差异影响:
#!/bin/bash printf 'a \b c\n' | awk 'match( $0, /[\x00-\x1F\x7F]/ ) { print RSTART }'
执行后会正确输出3。
方案2:强制使用C locale解析字符类
如果必须保留[:cntrl:]写法,可以通过设置LC_ALL=C强制awk使用C locale,避免locale对字符类解析的干扰:
#!/bin/bash printf 'a \b c\n' | LC_ALL=C awk 'match( $0, /[[:cntrl:]]/ ) { print RSTART }'
C locale下旧BSD awk会严格遵循POSIX标准解析[:cntrl:],仅匹配ASCII控制字符。
内容的提问来源于stack exchange,提问作者Fravadona
相关产品推荐
相关产品推荐

