为什么大写字母包含在 awk 正则表达式中的一系列小写字母中?

Che*_*eng 8 awk regular-expression

$ echo ABC | awk '$0 ~ /^[a-b]/'
ABC
$ echo ABC | awk '$0 ~ /^[a-a]/'
$ echo ABC | awk '$0 ~ /^a/'
$ 
Run Code Online (Sandbox Code Playgroud)

你看。/[a-b]/捕获A,但/[a-a]//a/没有。为什么?

enz*_*tib 7

我认为这是一个“语言环境”问题。

在我的语言环境 it_IT 中,以下代码段

if [[ a < A ]]; then
  echo "a < A"
elif [[ a > A ]]; then
  echo "a > A"
else
  echo "a = A"
fi

if [[ b < A ]]; then
  echo "b < A"
elif [[ b > A ]]; then
  echo "b > A"
else
  echo "b = A"
fi
Run Code Online (Sandbox Code Playgroud)

显示

a < A
b > A
Run Code Online (Sandbox Code Playgroud)

所以这A(令人惊讶地)介于a和之间b,所以在范围内。

尝试执行

echo ABC | LC_COLLATE=C awk '$0 ~ /^[a-b]/'
Run Code Online (Sandbox Code Playgroud)

编辑

以下命令显示您的语言环境中的整理顺序:

echo $(LC_COLLATE=C printf '%s\n' {A..z} | sort)
Run Code Online (Sandbox Code Playgroud)

我机器上的输出是

` ^ _ [ ] a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
Run Code Online (Sandbox Code Playgroud)

(无法从 bash 的手册页了解序列表达式是否按区域设置整理顺序展开;似乎不是)。

  • 序列 eval 顺序无关紧要*在这种情况下*,因为您在序列生成后进行排序。但是,您的示例在排序旁边使用 LC_COLLATE 会更准确:“echo $(printf '%s\n' {A..z} | LC_COLLATE='C' sort)” ...这将与默认值正确对比case "echo $(printf '%s\n' {A..z} | LC_COLLATE='' sort)"。上面的原始语法实际上从未将本地修改的 LC_COLLATE 应用于排序命令 [当然,如果 LC_ALL 设置在某处,则所有赌注都将关闭...] (3认同)