ead*_*ter 5 character-encoding shell-script portability
我有一些带有 UTF8 编码字符的 shell 脚本,我想确保它们被正确解码,而不管机器语言环境设置如何。
是否可以强制 shell(bash 或 sh)检测正确的脚本编码?(类似于 python 或 ruby 编码 cookie 的东西)
解决方案可能是自定义shebang,例如:
#!/bin/bash --utf8
Run Code Online (Sandbox Code Playgroud)
该解决方案应旨在提高可移植性,因此没有必要坚持使用 bash。
编辑:也许我已经找到了使用递归脚本调用的可能解决方案:
# check if current locale is UTF8-based (otherwise this script may not work correctly)
locale | grep -q 'UTF-8'
if [ $? -ne 0 ]; then
export LC_ALL=en_GB.UTF-8
# recursive call this script with the modified environment
$0 "$@"
exit $?
fi
Run Code Online (Sandbox Code Playgroud)
Bash 将字符串存储为字节字符串,并根据当前LC_CTYPE
设置执行操作。因此无需重新启动 bash:只需将LC_CTYPE
或LC_ALL
变量设置为您所需的区域设置即可。请注意,如果将字符串存储在变量或函数中,重要的是扩展变量或执行函数中的相关命令时的编码。这是一个演示这一点的脚本:
#!/bin/bash\nLC_CTYPE=en_US.utf8\nv_utf8=\'\xc3\xa9\'\nn_utf8=${#v_utf8}\nf_utf8 () { tmp=\'\xc3\xa9\'; echo ${#tmp}; }\necho "UTF-8 in UTF-8: $n_utf8 $(f_utf8)"\nLC_CTYPE=en_US\nv_latin1=\'\xc3\xa9\'\nn_latin1=${#v_latin1}\nf_latin1 () { tmp=\'\xc3\xa9\'; echo ${#tmp}; }\necho "Latin 1 in Latin 1: $n_latin1 $(f_latin1)"\necho "UTF-8 in Latin 1: ${#v_utf8} $(f_utf8)"\nLC_CTYPE=en_US.utf8\necho "Latin 1 in UTF-8: ${#v_latin1} $(f_latin1)"\n
Run Code Online (Sandbox Code Playgroud)\n\n输出:
\n\nUTF-8 in UTF-8: 1 1\nLatin 1 in Latin 1: 2 2\nUTF-8 in Latin 1: 2 2\nLatin 1 in UTF-8: 1 1\n
Run Code Online (Sandbox Code Playgroud)\n\n正如您所看到的,字符串的长度是根据 的当前值计算的LC_CTYPE
,而与定义时的值无关。