Вопрос по bash, pattern-matching – Почему в регистре не учитывается регистр, когда nocasematch выключен?

6

Учитывая следующее:

$ echo $BASH_VERSION
4.2.10(1)-release

$ shopt | fgrep case
nocaseglob      off
nocasematch     off

$ case A in [a-z]) echo TRUE;; esac
TRUE

Я ожидаю, что заглавная букваA долженnot соответствует классу символов нижнего регистра[a-z], но это так. Почему это совпадение не удается?

nocaseglob не связано:If set, bash matches filenames in a case-insensitive fashion when performing pathname expansion (see Pathname Expansion above)хотя поведение все еще странно. Daenyth

Ваш Ответ

2   ответа
7

Таким образом, вы не можете надежно использовать тире. Если я не использую тире, это работает как ожидалось:

$ bash --version
GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ shopt -s nocasematch
$ case A in [abc]) echo TRUE;; esac
TRUE
$ shopt -u nocasematch
$ case A in [abc]) echo TRUE;; esac
$ 

Ноwith тире, он печатает TRUE независимо от настройкиnocasematch.

Bash здесь выполняет поиск по шаблону. Проверять, выписыватьсяэтот раздел справочного руководства где говорится, что с помощью дефиса МОЖЕТ интерпретировать[a-z] как[A-Za-z]! В нем рассказывается, как получить традиционную интерпретацию (установите LC_COLLATE или LC_ALL в C). В основном ваш язык по умолчанию сортировка в порядке словаря. Справочное руководство объясняет вещи довольно хорошо.

ADDENDUM

Хорошо, у меня есть стенограмма для вас.

$ shopt -u nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
$ shopt -s nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
$ LC_ALL=C
$ shopt -u nocasematch
$ case A in [a-z]) echo TRUE;; esac
$ shopt -s nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
7

Это связано с вашими настройками локали. В частности, последовательность упорядочения является последовательностью с нечувствительностью к регистру.

Например, сLC_COLLATE установлен вen_AU.utf8 (по умолчанию в моей системе), вы можете видеть, что он включает строчные и прописные буквы вместе:

pax> case A in [a-b]) echo TRUE;; esac
TRUE
pax> _

но, если вы избавитесь от спецификатора диапазона, он будет работать как положено:

pax> case A in [ab]) echo TRUE;; esac
pax> _

Это потому, что первое означаетbetween a and b inclusive который для этой последовательности сопоставления включает в себяA, Для последнего средстваa а такжеb только не диапазон, на который будет влиять последовательность упорядочения.

Если вы установите последовательность сортировки с учетом регистра, она будет работать так, как вы ожидаете:

pax> export LC_COLLATE="C"
pax> case A in [a-b]) echo TRUE;; esac
pax> 

Если вы просто хотите сделать это как разовую операцию, не влияя ни на что другое, вы можете сделать это в под-оболочке:

( export LC_COLLATE="C" ; case A in [a-b]) echo TRUE;; esac )

Похожие вопросы