Używam bash na Linuksie. Odnoszę sukces z następujących instrukcji if, ale czy to nie powinno zwrócić kodu błędu?
if [[ ■ = [⅕⅖⅗] ]] ; then echo yes ; fi
Kwadrat NIE jest równy żadnemu ze znaków, więc nie rozumiem, dlaczego dostaję kod sukcesu.
Ważne jest dla mnie zachowanie podwójnych nawiasów w moim przypadku.
Czy istnieje inny sposób wykonania zakresu w tym scenariuszu lub jakie inne sugestie?
C
nie zrobię tego tutaj, ponieważ nie są to znaki jednobajtowe.C.UTF-8
zrobiłbym tam, gdzie to możliwe.Odpowiedzi:
Jest to konsekwencja tego, że postacie mają tę samą kolejność sortowania.
Zauważysz to również
zwraca tylko jedną linię.
Albo to:
zwraca true (zgodnie z wymaganiami POSIX).
Większość ustawień narodowych dostarczanych z systemami GNU ma wiele znaków (a nawet sekwencje znaków (sekwencje zestawiania)), które mają tę samą kolejność sortowania. W przypadku tych ■ ⅕⅖⅗ dzieje się tak dlatego, że kolejność nie jest zdefiniowana, a znaki, których kolejność nie jest zdefiniowana, mają w systemach GNU tę samą kolejność sortowania. Są znaki, które są wyraźnie zdefiniowane jako mające tę samą kolejność sortowania, jak Ș i Ş (chociaż nie ma (jak dla mnie zresztą) prawdziwej logiki ani spójności w tym, jak to się robi).
To jest źródło dość zaskakujących i fałszywych zachowań. I podniósł kwestię bardzo niedawno na grupie Austin (ciało za POSIX i Single Unix Specification) listy i dyskusja wciąż trwa od dnia 2015-04-03.
W tym przypadku pytanie, czy
[y]
powinien pasować do tego samegox
miejscax
iy
sortować, jest dla mnie niejasne, ale ponieważ wyrażenie w nawiasie ma pasować do elementu zestawiającego, sugeruje to, żebash
zachowanie jest oczekiwane.W każdym razie przypuszczam, że
[⅕-⅕]
przynajmniej[⅕-⅖]
powinienem się zgadzać■
.Zauważysz, że różne narzędzia zachowują się inaczej. ksh93 zachowuje się jak
bash
, GNUgrep
lubsed
nie. Niektóre inne muszle zachowują się inaczej, niektóre z nich sąyash
jeszcze bardziej wadliwe.Aby zachować spójne zachowanie, potrzebujesz ustawień regionalnych, w których wszystkie postacie sortują się inaczej. Lokalizacja C jest typowa. Jednak zestaw znaków w ustawieniach regionalnych C w większości systemów to ASCII. W systemach GNU ogólnie masz dostęp do
C.UTF-8
ustawień narodowych, których można użyć zamiast tego do pracy na znaku UTF-8.Więc:
lub standardowy odpowiednik:
powinien zwrócić wartość false.
Inną alternatywą byłoby ustawienie tylko
LC_COLLATE
C, która działałaby na systemach GNU, ale niekoniecznie na innych, w których nie byłaby w stanie określić kolejności sortowania znaków wielobajtowych.Jedną z lekcji jest to, że równość nie jest tak jasnym pojęciem, jakiego można by się spodziewać, jeśli chodzi o porównywanie łańcuchów. Równość może oznaczać od najostrzejszego do najmniej surowego.
Teraz dla 2 lub 3, przy założeniu, że oba ciągi zawierają prawidłowe znaki. W UTF-8 i niektórych innych kodowaniach niektóre sekwencje bajtów nie tworzą prawidłowych znaków.
1 i 2 niekoniecznie są z tego powodu równoważne lub ponieważ niektóre znaki mogą mieć więcej niż jedno możliwe kodowanie. Tak jest zwykle w przypadku stanowego kodowania, takiego jak ISO-2022-JP, gdzie
A
można wyrazić jako41
lub1b 28 42 41
(1b 28 42
jest to sekwencja przełączania na ASCII i można wstawić tyle, ile chcesz, to nie robi różnicy), chociaż ja nie spodziewałbym się, że tego rodzaju kodowanie będzie nadal używane, a narzędzia GNU przynajmniej na ogół nie działają z nimi poprawnie.Uważaj również, że większość programów spoza GNU nie radzi sobie z wartością 0 bajtów (znak NUL w ASCII).
To, która z tych definicji zostanie użyta, zależy od narzędzia i jego implementacji lub wersji. POSIX nie jest w tym w 100% jasny. W ustawieniach regionalnych C wszystkie 3 są równoważne. Poza tym YMMV.
źródło
é
ié
bycie tym samym ciągiem, ale niee
. Pojęcie uporządkowania przez POSIX rzadko ma rację, jest zbyt mocno oparte na znakach i nie bierze pod uwagę najczęstszych sposobów sortowania ciągów (np. Francuskie słowniki nie używają porządku leksykograficznego do sortowania słów: wykonują pierwsze przejście leksykograficzne z ignorowanymi akcentami i następnie użyj akcentów, aby zdecydować o powiązaniu).Robisz to źle
=
i==
nie jesteś taki sam.Spróbuj tych przykładów:
źródło
=
powinien być używany do sprawdzania równości. Problemem są brakujące cytaty, a nie operator.man bash
Mówi także w[[
sekcji: „Operator = jest równoważny ==.”[[...]]
operatora. I = i == są takie same w powłokach, w których został zaimplementowany (ksh / bash / zsh) i dla dopasowania wzorca, a nie równości.