您的字符串使用多字节编码,特别是 UTF-8;花括号每个是三个字节。但是您的sed
实现将每个字节视为一个单独的字符。这可能是由于您的语言环境设置。我可以通过将我的语言环境设置为“C”(旧的默认 POSIX 语言环境,假定为 ASCII)来重现您的问题:
$ LC_ALL=C sed -E "s/[‘’]/'/g" <<<'‘foo’' # C locale, single-byte chars
'''foo'''
但是在我的 en_US.UTF-8(“用 UTF-8 编码的美国英语”)的正常语言环境中,我得到了想要的结果:
$ LC_ALL=en_US.UTF-8 sed -E "s/[‘’]/'/g" <<<'‘foo’' # UTF-8 locale, multibyte chars
'foo'
您运行它的方式sed
不是[‘‘]
四个字符的序列,而是八个字符的序列。因此,括号之间的六个字节中的每一个——或者至少是在这些字节中找到的四个唯一值中的每一个——都被认为是字符类的成员,并且每个匹配的字节都被撇号单独替换。这就是为什么您的三字节大引号每个都被三个撇号取代的原因。
使用交替的版本有效,因为每个交替可以是多个字符;即使sed
仍然将 ' 和 ' 视为三个字符序列而不是单个字符,但该处理不会改变结果。
因此,请确保为您的文本编码正确设置您的语言环境,看看是否能解决您的问题。