Я использую Bash на Linux. Я получаю успех от следующего оператора if, но разве это не должно возвращать код ошибки?
if [[ ■ = [⅕⅖⅗] ]] ; then echo yes ; fi
Квадрат НЕ равен ни одному из символов, поэтому я не понимаю, почему я получаю код успеха.
Для меня важно сохранить двойные скобки в моем случае.
Есть ли другой способ сделать диапазон в этом сценарии, или какие-либо другие предложения?
C
здесь не пойдет, так как это не однобайтовые символы.C.UTF-8
сделал бы, где доступно.Ответы:
Это следствие того, что символы имеют одинаковый порядок сортировки.
Вы также заметите, что
возвращает только одну строку.
Или это:
возвращает true (как того требует POSIX).
Большинство локалей, поставляемых с системами GNU, имеют ряд символов (и даже последовательности символов (последовательности упорядочения)), которые имеют одинаковый порядок сортировки. В случае этих it's ■ это потому, что порядок не определен, и те символы, порядок которых не определен, в конечном итоге имеют одинаковый порядок сортировки в системах GNU. Есть символы, которые явно определены как имеющие один и тот же порядок сортировки, как Ș и Ş (хотя нет никакой очевидной (для меня в любом случае) реальной логики или последовательности в том, как это делается).
Это источник довольно удивительного и поддельного поведения. Недавно я поднял этот вопрос в списке рассылки Austin group (основная часть POSIX и Single UNIX Specification), и по состоянию на 2015-04-03 обсуждение продолжается.
В этом случае вопрос о том,
[y]
должно ли совпадать,x
гдеx
иy
сортировать то же самое, мне неясен, но так как выражение в скобках предназначено для соответствия элементу сортировки, это говорит о том, чтоbash
поведение ожидается.В любом случае, я полагаю,
[⅕-⅕]
или, по крайней мере,[⅕-⅖]
должны совпадать■
.Вы заметите, что разные инструменты ведут себя по-разному. ksh93 ведет себя как
bash
GNUgrep
илиsed
нет. Некоторые другие оболочки имеют различное поведение, некоторые, какyash
еще более глючные.Чтобы иметь согласованное поведение, вам нужен языковой стандарт, в котором все символы сортируются по-разному. Язык Си является типичным. Однако набор символов в локали C в большинстве систем является ASCII. В системах GNU у вас обычно есть доступ к
C.UTF-8
локали, которую можно использовать вместо этого для работы с символом UTF-8.Так:
или стандартный эквивалент:
должен вернуть false.
Другой альтернативой может быть установка только
LC_COLLATE
на C, который будет работать в системах GNU, но не обязательно в других, где он не сможет указать порядок сортировки многобайтовых символов.Одним из уроков этого является то, что равенство не так ясно, как можно было бы ожидать, когда речь идет о сравнении строк. Равенство может означать от самого строгого до наименее строгого.
Теперь для 2 или 3 предполагается, что обе строки содержат допустимые символы. В UTF-8 и некоторых других кодировках некоторые последовательности байтов не образуют допустимых символов.
1 и 2 не обязательно эквивалентны из-за этого или из-за того, что некоторые символы могут иметь более одной возможной кодировки. Это, как правило, в случае кодировок с сохранением состояния, таких как ISO-2022-JP, где они
A
могут быть выражены как41
или1b 28 42 41
(1b 28 42
являясь последовательностью для переключения на ASCII, и вы можете вставить столько из них, сколько захотите, это не будет иметь значения), хотя я не ожидал бы, что эти типы кодирования все еще используются, и инструменты GNU, по крайней мере, обычно не работают с ними должным образом.Также имейте в виду, что большинство не-GNU утилит не могут работать со значением 0 байт (символ NUL в ASCII).
Какое из этих определений используется, зависит от реализации или версии утилиты и утилиты. POSIX не на 100% ясно об этом. В локали C все 3 эквивалентны. За пределами этого YMMV.
источник
é
иé
быть одной и той же строкой, но не такe
. Понятие порядка сортировки POSIX редко бывает правильным, оно слишком сильно основано на символах и не учитывает наиболее распространенные способы сортировки строк (например, французские словари не используют лексикографический порядок для сортировки слов: они делают первый лексикографический проход с игнорированием акцентов и тогда используйте акценты, чтобы решить связи).Вы делаете это неправильно,
=
и==
не то же самое.Попробуйте эти примеры:
источник
=
должен использоваться для проверки равенства. Проблема в пропущенных кавычках, а не в операторе.man bash
в[[
разделе говорится : «Оператор = эквивалентен ==.»[[...]]
оператор. И = и == одинаковы в оболочках, где они реализованы (ksh / bash / zsh) и для сопоставления с образцом, а не с равенством.