Contents

Linux中的环境变量

1. 概述

在本教程中,我们将介绍 Linux 中存在的标准语言环境变量。我们将介绍一些示例和用例,并了解它们是如何工作的。

在此过程中,我们将了解到它们在多种场景中为我们提供帮助——在处理语言、时间甚至操作系统使用的字符编码时。

2. 环境变量优先级

locale 环境变量告诉操作系统如何显示或输出某些类型的文本。它们具有优先级,使我们能够影响哪些将在各种情况下发挥作用:

  1. LANGUAGE
  2. LC_ALL
  3. LC_xxx,同时考虑到语言环境类别
  4. LANG

例如,我们可以使用LANG将法语设置为语言,但使用LC_TIME将其设置为美国日期时间格式。 让我们仔细看看各种语言环境变量,看看这个优先级方案是如何发挥作用的。

3. 语言环境变量

在我们进入 locale 环境变量之前,让我们使用locale 命令输出我们当前的设置:

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

接下来,我们将观察这些变量如何影响我们的输出,并了解它们如何与其他环境变量相互作用和协同工作。

3.1. LANG

LANG环境变量处理 Linux 系统的语言。当我们使用LANG变量指定一种语言时,它将使用该变量以我们选择的语言打印出消息。如果未设置语言,或者消息没有该语言的翻译,则默认为英语:

$ export LANG=es_ES.UTF-8
$ man man
MAN(1) Utilidades del paginador del manual MAN(1)
NOMBRE
man - interfaz de los manuales de referencia del sistema
SINOPSIS
man [opciones de man] [[sección] página ...] ...
// ...
$ man cat
CAT(1)                                           User Commands
NAME
       cat - concatenate files and print on the standard output
SYNOPSIS
       cat [OPTION]... [FILE]...
// ...

在这里,我们可以看到如何使用西班牙语打印“ man man ”命令的输出。我们还了解到,由于“ man cat ”命令没有西班牙语翻译,因此默认使用英语。

3.2. LC_xxx

现在,我们将看看一些LC_xxx变量以及它们如何与西班牙语的新LANG设置交互。

我们首先要看的是LC_TIME,它适用于日期和时间格式。例如,如果我们从一个国家迁移到另一个国家,并且我们希望我们的系统适应该国家的日期时间格式,这很有用:

$ date
joi 25 iunie 2020, 22:58:30 +0300
$ export LC_TIME=en_US.UTF-8
$ date
Thu 25 Jun 2020 10:58:30 PM EEST

在第一个命令中,我们看到罗马尼亚格式的日期,因为我们将LC_TIME变量设置为ro_RO.UTF-8。当我们将其更改为美国英语时,我们会看到相同的日期和时间,但以不同的格式报告。

** LC_MESSAGES负责以某种语言打印出消息**,类似于LANG。由于它是LC_xxx变量集的一部分,它将覆盖LANG变量。让我们检查:

$ locale | grep -w LANG
LANG=en_US.UTF-8
$ export LC_MESSAGES=de_DE.UTF-8
$ man man
MAN(1)                                      Dienstprogramme für Handbuchseiten
BEZEICHNUNG
       man - eine Oberfläche für die System-Referenzhandbücher
ÜBERSICHT
       man [man Optionen] [[Abschnitt] Seite ...] ...
// ...

另一个值得注意的语言环境变量是** LC_NUMERIC,负责格式化**操作系统打印的数字:

$ env LC_NUMERIC=en_US.UTF8 printf '%f\n' 1233.14
1233.140000
$ env LC_NUMERIC=de_DE.UTF8 printf '%f\n' 1233.14
1233,140000

在这里,我们看到了分隔符中两种数字格式的区别。

其他LC_xxx环境变量在某些场景中也很重要且有用。我们只需要知道如何正确使用它们。

3.3. LC_ALL环境变量

LC_ALL是最强的语言环境变量,除了LANGUAGE它优先覆盖所有其他变量,并且在需要区域设置时首先由系统检查。因此,应该谨慎使用它,并且只有当我们试图解决的问题没有其他解决方案时。

我们通常在不希望用户干预的脚本或程序中使用此环境变量,并且我们应该在完成脚本执行时将其重置为之前的值。 让我们看看当我们使用 UTF-8 编码将LC_ALL设置为英语时,我们的语言环境变量会发生什么:

$ export LC_ALL=en_EN.UTF-8 ## setting LC_ALL to English with UTF-8 encoding
$ locale
LANG=es_ES.UTF-8
LANGUAGE=en_US
LC_CTYPE="en_EN.UTF-8"
LC_NUMERIC="en_EN.UTF-8"
LC_TIME="en_EN.UTF-8"
LC_COLLATE="en_EN.UTF-8"
LC_MONETARY="en_EN.UTF-8"
LC_MESSAGES="en_EN.UTF-8"
LC_PAPER="en_EN.UTF-8"
LC_NAME="en_EN.UTF-8"
LC_ADDRESS="en_EN.UTF-8"
LC_TELEPHONE="en_EN.UTF-8"
LC_MEASUREMENT="en_EN.UTF-8"
LC_IDENTIFICATION="en_EN.UTF-8"
LC_ALL=en_EN.UTF-8

在这里,我们看到LC_ALL变量已覆盖所有其他语言环境变量。只要LC_ALL存在,我们就不能更改我们的设置:

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

要重置它,我们可以将一个空值导出到LC_ALL

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

在这里我们看到,当我们重置LC_ALL环境变量时,语言环境设置会重置为导出之前的状态。

3.4. LC_ALLsort命令

LC_ALL设置为特定值“C”是一种简单而强大的方法,可以强制语言环境使用默认语言,同时使用按字节排序。

接下来,让我们看看LC_ALL变量如何改变 sort命令的结果。

假设我们有一个 letters.txt文件:

$ cat letters.txt
b
B
A
c
a
C
D
d

我们可以使用sort命令对文件进行排序:

$ sort letters.txt 
a
A
b
B
c
C
d
D

上面的输出显示字母按字母顺序排序。 但是,有时,我们希望按 ASCII 码对文件进行排序。在这种情况下,我们可以设置*LC_ALL=”C”*来强制按字节排序:

$ LC_ALL="C" sort letters.txt 
A
B
C
D
a
b
c
d

值得一提的是,在上面的命令中,LC_ALL=”C”设置仅会更改LC_ALL变量以执行排序命令。当前 shell 中的LC_ALL环境变量没有改变。

3.5. LANGUAGE

** LANGUAGE环境变量可以有一个或多个语言值,并负责显示消息的语言顺序**。当我们设置了LC_ALL环境变量时,它是唯一可以更改的环境变量。

让我们看看它的实际效果:

$ export LC_ALL=en_US.UTF-8
$ export LANGUAGE=fr_FR:en_EN
$ man man
MAN(1)                                 Utilitaires de l'afficheur des pages de manuel
NOM
       man - an interface to the system reference manuals
SYNOPSIS
       man [man options] [[section] page ...] ...
// ...

即使我们将LC_ALL设置为英语,我们也有一些法语,因为我们看到的文本有一些现有的法语翻译,并且由于LC_ALLLANGUAGE覆盖,它向我们显示法语文本。