13

LANG我正在尝试通过更改变量来更改 urxvt 当前会话中的编码。但是,它似乎不会立即适用。这是我所做的:

可用的语言环境:

$ locale -a
C
en_US.utf8
POSIX
ru_RU.koi8r
ru_RU.utf8

在设置新的语言环境之前:

$ echo "а" | od -t x1
0000000 d0 b0 0a # good! UTF-8
#       | a ||NL|

后:

$ export LANG=ru_RU.KOI8-R
$ echo "а" | od -t x1
0000000 d0 b0 0a # hm..expect 'c1 0a'

通过运行 fork 新的 urxvt 实例$ urxvt &,最终得到我想要的:

$ echo "а" | od -t x1
0000000 c1 0a

为什么不LANG首先改变行为?

4

1 回答 1

16

有两个因素:

  • 您可能正在使用带有内置 echo 的外壳(并且没有通知外壳您正在更改语言环境)
  • LANG不是检查的第一个环境变量。根据locale(7),LC_ALL并且LC_CTYPE将首先检查:
       如果 setlocale(3) 的第二个参数是一个空字符串,“”,对于
       默认语言环境,使用以下步骤确定:

       1.如果存在非空环境变量LC_ALL,则取值
              使用 LC_ALL。

       2.如果环境变量与其中一个同名
              上述类别存在且非空,其值用于
              那个类别。

       3.如果存在非空环境变量LANG,则值为
              使用 LANG。

对于后者,请查看locale命令的输出,其中列出了将使用的所有环境变量:

$ export LANG=ru_RU.KOI8-R
$ locale
LANG=ru_RU.KOI8-R
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8

只是改变LANG不应该改变其他变量,但改变LC_ALL通常会这样做。

$ export LC_ALL=ru_RU.KOI8-R
$ locale
LANG=ru_RU.KOI8-R
LANGUAGE=
LC_CTYPE="ru_RU.KOI8-R"
LC_NUMERIC="ru_RU.KOI8-R"
LC_TIME="ru_RU.KOI8-R"
LC_COLLATE="ru_RU.KOI8-R"
LC_MONETARY="ru_RU.KOI8-R"
LC_MESSAGES="ru_RU.KOI8-R"
LC_PAPER="ru_RU.KOI8-R"
LC_NAME="ru_RU.KOI8-R"
LC_ADDRESS="ru_RU.KOI8-R"
LC_TELEPHONE="ru_RU.KOI8-R"
LC_MEASUREMENT="ru_RU.KOI8-R"
LC_IDENTIFICATION="ru_RU.KOI8-R"
LC_ALL=ru_RU.KOI8-R
于 2017-05-13T13:57:31.153 回答