【问题标题】:How to make grep [A-Z] independent of locale?如何使 grep [A-Z] 独立于语言环境?
【发布时间】:2011-10-11 14:35:55
【问题描述】:

我正在做一些日常的 grepping,突然发现一些看似微不足道的事情不起作用:

$ echo T | grep [A-Z]

不匹配。

为什么T不在A-Z范围内?

我稍微改变了正则表达式:

$ echo T | grep [A-Y]

一场比赛!

哇! T 在 A-Y 内而不在 A-Z 内如何?

显然这是因为我的环境设置为爱沙尼亚语言环境,其中 Y 位于字母表的末尾,而 Z 位于中间的某个位置:ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY

$ echo $LANG
et_EE.UTF-8

这一切让我有点震惊。 99% 的时间我 grep 计算机代码,而不是爱沙尼亚文学。我一直在错误地使用 grep 吗?我过去因此而犯了哪些错误?

在尝试了几件事后,我得出了以下解决方案:

$ echo T | LANG=C grep [A-Z]

这是使 grep 独立于语言环境的推荐方法吗?

还有更多...定义这样的别名是否安全:

$ alias grep="LANG=C grep"

PS.我也想知道为什么像[A-Z]这样的字符范围首先依赖于语言环境,而\w似乎不受语言环境的影响(尽管手册上说@987654328 @ 等同于 [[:alnum:]] - 但我发现后者取决于语言环境,而 \w 则不)。

【问题讨论】:

  • 请再试一次,但请引用您的表达式grep '[A-Z]',以确保外壳不会扩展它。
  • 加引号和不加引号对我来说都是一样的。
  • 工作方式相同,只是因为您没有一个名为 A 到 Z 的文件。shell 尝试扩展 [A-Z],但没有找到任何内容,然后就不管它了。使用引号始终将模式传递给 grep。
  • 谢谢,我实际上并不知道 Bash 支持扩展这种东西。但我实际上一直在引用 grep 参数——我只是想我会不使用它们以缩短代码示例。现在又变聪明了。
  • 问题“这是使 grep 语言环境独立的推荐方法吗?”不合适。 grep 必须使用 some 语言环境;它根本无法在没有任何语言环境的情况下运行。我想你可能想改写问“这是如何让 grep 使用我习惯的旧 ASCII 语言环境吗?”,这确实有一个答案:是的。 LC_ALL=C 将为您提供旧的 ASCII 字符集和整理顺序。 LC_COLLATE=C 将允许完整的本地语言环境字符集,但要确保它以熟悉的 ASCII 方式排序。这就是你想要的吗?

标签: grep locale


【解决方案1】:

Linux 和 FreeBSD grep 自然支持的 POSIX 正则表达式以及其他一些应要求支持的正则表达式具有一系列支持语言环境的 [:xxx:] 模式。有关详细信息,请参见手册页。

 grep '[[:upper:]]' 

由于 [] 是模式名称的一部分,因此您也需要外部 [],无论它看起来多么奇怪。

随着这些 : 代码的出现,经典的 \w 等,严格地保留在 C 语言环境中。因此,您选择的模式决定了 grep 是否使用当前语言环境。

[A-Z] 应该遵循区域设置,但您可能需要设置 LC_ALL 而不是 LANG,尤其是当系统将 LC_ALL 设置为不同的值时。

【讨论】:

  • 所以你说 [A-Z] 严格地保留在 C 语言环境中?但我的整个问题是它不在 C 语言环境中。
  • 尝试设置 LC_ALL 环境变量而不是 LANG。
  • LC_ALL 可能是比 LANG 更好的变量,因为它是 grep 首先检查的变量。但目前它对我没有任何影响。
  • 使用 date 命令是测试语言环境是否启用的快速方法:LC_ALL=et_EE date
猜你喜欢
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-05
  • 2021-03-28
相关资源
最近更新 更多