解释导出 LANG、 LC_CTYPE 和 LC_ALL 的效果

我刚刚安装了 Linux Mint17,遇到了一个问题,我不能在终端使用俄语。(我看到的是 ?而不是字母。)

在一个论坛上,我找到了这个解决方案:

在 ~/. profile 中添加:

export LANG=ru_RU.UTF-8
export LC_CTYPE=ru_RU.UTF-8
export LC_ALL=ru_RU.UTF-8

它有所帮助,但也改变了我的接口语言为俄语(这是我不想要的)。这甚至不是一个问题,但无论如何,我想知道,这段代码是如何工作的(每一行)。

81074 次浏览

请参阅 UNIX 规范的 环境变数页面:

  • LANG此变量确定母语的区域设置类别, 当地海关和编码字符集在没有 LC_ALL和 其他 LC_*(LC_COLLATELC_CTYPELC_MESSAGESLC_MONETARY, LC_NUMERICLC_TIME)环境变量 应用程序来确定用于错误消息和 指令、校对序列、日期格式等等

  • LC_ALL此变量确定所有区域设置类别的值。 ABc0环境变量的值优先于任何 以 LC _ (LC _ COLLATE 开始的其他环境变量, LC_CTYPELC_MESSAGESLC_MONETARYLC_NUMERICLC_TIME)和 LANG 环境变量

  • LC_CTYPE此变量确定字符的区域设置类别 处理功能,例如 tolower()toupper()isalpha() 环境变量决定了序列的解释 字节的文本数据作为字符(例如,单字符-相对于 多字节字符)、字符的分类(例如, 字母、数字、图形)和字符类的行为。 此变量的其他语义(如果有的话)是 取决于实施情况

我会详细解释:

export LANG=ru_RU.UTF-8

这是一个 shell 命令,它将导出一个具有给定值 ru_RU.UTF-8的名为 LANG的环境变量。这指示国际化程序使用俄语(ru)、俄语变体(RU)和控制台输出的 UTF-8编码。

一般来说,这一行就足够了。

另一个:

export LC_CTYPE=ru_RU.UTF-8

做类似的事情,但它告诉程序不要改变语言,而只是把 CTYPE改成俄语。如果程序可以将文本更改为大写,那么它将使用俄语规则,即使文本本身可能是英语。

值得一提的是,混合 LANGLC_CTYPE可以产生意想不到的结果,因为很少有人这样做,所以它是相当未经测试,除非也许:

export LANG=ru_RU.UTF-8
export LC_CTYPE=C

这将使程序输出为俄文,但 CTYPE 标准旧式 C 风格。

最后一行,LC_ALL是最后的手段,它将使程序忽略所有其他 LC_*变量并使用。我认为你永远不应该把它写在一个配置文件行,但使用它来运行一个程序在一个给定的语言。例如,如果你想写一个 bug 报告,你不想要任何类型的本地化输出,你不知道哪些 LC_*变量被设置:

LC_ALL=C program

关于更改所有程序的语言或仅更改控制台,这取决于您将这些行放在何处。我把我的应用程序放在 ~/.bashrc中,这样它们就不会应用到 GUI 上,只会应用到 bash 控制台上。

您的 .bashrc文件是要读取的第一个文件之一,它包含您的 shell 会话的各种配置。

来自 Bashrc、 . bash _ profile 和. environment 之间的区别是什么?:

. bashrc 只能由交互式和非登录的 shell 读取

正如 定义带或不带导出的变量中所解释的:

Export 使变量对子进程可用。

或者

具体来说,export 通过环境使变量对子进程可用。

摩尔

LANGLC_CTYPELC_ALL是特殊的环境变量,它们被导出到 shell 环境(help export)后,就可以被某些支持语言环境(C 语言的自然语言格式)的程序读取。

每个变量都为特定的例程集设置 C 库的自然语言格式化风格的概念,例如:

  • LC_ALL-通用地设置整个语言环境
  • LC_CTYPE-为 ctypemultibyte函数设置一个区域设置。这可以控制大小写、字母或非字母字符等字符的识别。

其他如 LC_COLLATE(用于字符串排序例程)、 LC_MESSAGES(用于消息目录)、 LC_MONETARY(用于格式化货币值)、 LC_NUMERIC(用于格式化数字)、 LC_TIME(用于格式化日期和时间)。

关于 LANG,它被用来替代任何未设置的 LC_*变量(参见: man locale)。

参见: man setlocale(BSD) ,man locale

因此,当调用某些 C 函数时(如 setlocalectypemultibytecatopenprintf等) ,它们从配置文件和本地环境中读取语言环境设置,以便按照 C 编程语言标准(参见: ctype0)控制和格式化自然语言格式化样式

参见: C 库-< locale.h >

export很混乱 真正的意思是 mark-for-export

它意味着子进程将在以后创建,并且实际的导出将在这个时候完成。


事件的 export顺序是: 1-分配MARK和... ... 双叉


1) 创建一个新的 局部 shell 变量局部 shell 变量,为它赋值,并为 回见导出标记这个变量。

2) 如果当前的 shell 脚本是 FORKED (即创建并运行任何子进程) ,那么使用导出变量 作为许多环境变量之一的 COPY 启动一个子进程。

Nb (请注意) : 直到步骤2,可能在发出 export声明很久之后,变量才真正被导出。所以: export只标记了 LANG。它不出口朗。


按照惯例,导出的变量以大写形式命名。

因为 LANG 只是一个副本,所以如果子变量稍后修改了这个变量,那么它只是为自己修改了它。父母没有看到孩子的修改。

请注意,还有许多其他环境变量从父进程传递给子进程。这些变量包括父进程也从其父进程获得的所有其他环境变量。

所以子元素继承父元素的所有环境变量,
+ 父代标记为 export的任何附加值,
减去任何显式为 unset的变量。


换句话说,我们需要考虑两个进程: 父进程和任何未来的子进程。

您正在运行的进程,在本例中为 profile,就是我们所称的“父进程”。

profile可以产生一个或多个子进程,例如,如果您在配置文件中所做的事情之一是运行一个程序。然后(通常)将该程序作为 profile的子进程运行。(如果使用 ABC2或 ABC3表示法以配置文件的形式提供源文件,则不会出现这种情况,其中提供的源文件与 profile运行在相同的进程中。)


export LANG=ru_RU.UTF-8
export LC_CTYPE=ru_RU.UTF-8
export LC_ALL=ru_RU.UTF-8

现在让我们看看这三个环境变量的影响。

LANG 是用户通常设置以影响程序运行所使用的语言的内容。在终端输入 env | grep LANG时,应该看到 LANG 被设置为 <language>_<country-code>.<character-encoding>,例如 LANG = en _ US。UTF-8.

LC _ CTYPE 是对 LANG 的重写,只重写所使用的字符集。LANG 的所有其他特性(类别)仍然按照 LANG 设置使用,例如 LC _ TELEPHONE。

LC _ ALL 是进一步的覆盖。它覆盖了 LC _ CTYPE 和由 LANG 设置为给定语言和代码集的所有区域设置类别。请注意,LC _ ALL 不应该像配置文件本身那样持久地设置。它只是作为一个临时的整个语言环境覆盖,即覆盖所有类别,如 LC _ TELEPHONE、 LC _ MONETARY、 LC _ CTYPE 等。