如何在 bash 中检查变量是否包含有效的 UTF-8 字符串,而不包含任何特殊控制字符(例如换行符、退格符或回车符等)?
答案1
假设区域设置使用 UTF-8 作为其字符编码(使用 进行检查locale charmap
):
[[ $string =~ ^[^[:cntrl:]]*$ ]]
应该可以工作,除了至少在 GNU 系统上,它无法拒绝包含代码点高于 0x110000 的字符的 UTF-8 编码的字符串(这些字符是在 UTF-8 编码的当前定义中不再有效)。这取决于系统的正则表达式库bash
用于进行模式匹配。
GNU 也是如此expr
:
expr " $string" : ' [^[:cntrl:]]*$' > /dev/null
在这里,您可能想要切换到zsh
UTF-8 语言环境中的位置:
set -o extendedglob
[[ $string = [' '-$'\ud7fff'$'\ue000'-$'\U10FFFF']# && $string != *[[:cntrl:]]* ]]
无论系统如何,都应该一致地工作(至少对于有效字符的匹配;您可能会发现字符被分类为 的系统之间存在差异[:cntrl:]
)。
在 zsh glob 模式中,多字节字符区域设置中的字符范围基于字符的宽字符值,在 UTF-8 中它始终是 Unicode 代码点。不构成有效字符一部分的字节将在 0xD800..0xDFFF UTF16 代理项对的第二部分中分配 0xDC80..0xDCFF 范围内的 wchar_t 值,这些代理项对不是字符(aUnicode 认可的通用方法能够处理任意字节序列)。
bash glob 模式中的字符范围处理大多是随机的,所以不能在这里使用。
您可能还想考虑如何处理非字符,私人使用字符,当前未在您的系统正在使用的 Unicode 版本中分配的字符。的概念控制对于 Unicode 来说,字符也相当模糊。是 U+202E RIGHT-TO-LEFT OVERRIDE 字符、U+FEFF BOM 字符、标签人物例如控制人物?