LInux locale设置对Ksh浮点算术影响
今天收集到一个关于shell的有意思问题,分享给大家。
问题
有一个ksh脚本,功能是浮点数之间比较,脚本如下所示:
#!/bin/ksh
a=4.5
b=4.0
if [ $a -gt $b ]; then
echo "a > b"
else
echo "a <= b"
fi
语法没有问题,很多平台下运行都没有问题,但在某一个账户下运行会报语法错误。
执行脚本报错如下:
$ ./test.sh
./new.sh[6]: [: 4.5: arithmetic syntax error
a <= b
最后发现是系统区域(locale)相关环境变量设置导致的。
$ locale
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=
locale环境变量
Linux系统下需要进行区域设置,用来确定数字格式、日期格式、货币符号、语言等与特定地区或语言相关的设置。
Linux中区域设置相关环境变量有
- LANGUAGE
- LC_ALL
- LC_xxx (包括LC_TYPE、LC_NUMERIC、LC_TIME等)
- LANG
程序会根据以上环境变量顺序查询区域设置信息,程序处理输出会产生差异。环境变量介绍见参考一链接。
那么为什么locale设置会影响ksh脚本。
在网上查资料,说是因为Ksh受LC_NUMERIC
中decimal_point
设置影响,进而影响浮点算术。
通过以下脚本输出en_US.UTF-8
和zh_CN.UTF-8
的LC_NUMERIC
设置进行对比。
#!/bin/bash
#
CATS="LC_NUMERIC"
LANG=en_US.utf8 locale -k $CATS > en_US.utf8.numeric.out
LANG=zh_CN.utf8 locale -k $CATS > zh_CN.utf8.numeric.out
LANG=C locale -k $CATS > C.numeric.out
对比发现decimal_point
没有差异,都是.
为小数点。
decimal_point="."
thousands_sep=""
grouping=-1
numeric-decimal-point-wc=46
numeric-thousands-sep-wc=0
numeric-codeset="ANSI_X3.4-1968"
但是在脚本开始设置LC_NUMERIC=C
,使用C语言locale设置,脚本执行正常,不再报错。是否有可能是在zh_CN.UTF-8
中文环境中小数点.
和其它设置冲突了?
locale设置除了上面对ksh脚本浮点算术影响,还会对很多命令产生影响,具体可以查看参考二链接。
但一般建议使用LC_ALL=C
重置LC_xxx
的设置。
所以建议在脚本开始处设置LC_ALL=C
方式避免区域设置引起的意想不到的问题。
参考资料
https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
https://unix.stackexchange.com/questions/87745/what-does-lc-all-c-do

