Bash Globbing nicht wie erwartet

8

Dies ist eine Hausaufgabenfrage:

Ordnen Sie allen Dateinamen 2 oder mehr Zeichen zu, die mit einem Kleinbuchstaben beginnen, aber nicht mit einem Großbuchstaben enden.

Ich verstehe nicht, warum meine Lösung nicht funktioniert.

Also habe ich folgendes ausgeführt:

touch aa
touch ha
touch ah
touch hh
touch a123e
touch hX
touch Ax

ls [a-z]*[!A-Z]

Ausgabe:

aa  ha

Meine Frage: Warum stimmte es nicht mit "ah", "hh" oder "a123e" überein?

Dunkles Herz
quelle
Funktioniert für mich richtig unter der mkshSchale, aber nicht bash --posix, also muss es eine spezielle Regel für Bash geben
Sergiy Kolodyazhnyy
@Serg, beachten Sie, dass das Verhalten für [AZ] von POSIX nur im Gebietsschema C angegeben wird. mkshwie zsh's [A-Z]passt Ézum Beispiel nicht auf . Die [A-Z]Übereinstimmungen von ksh93 sind aktiviert, Éaber nicht aktiviert h.
Stéphane Chazelas

Antworten:

9

Dies ist ein Problem mit dem Gebietsschema . Erweitert in Ihrem Gebietsschema [A-Z]auf etwas wie [AbBcZ...zZ](und wahrscheinlich auch auf andere wie Zeichen mit Akzent) und [^A-Z]bedeutet daher ain Ihrem Beispiel (und nur in Ihrem Beispiel) "Dateien, die mit " enden .

Wenn Sie eine solche Überraschung vermeiden möchten, müssen Sie eine Möglichkeit festlegen, LC_COLLATE=C da die Sortierung der Teil Ihrer Gebietsschemaeinstellungen ist, der für die Sortierreihenfolge verantwortlich ist. Auch leer, LC_ALLwenn es gesetzt ist, da es Vorrang haben würde.

$ ls [a-z]*[^A-Z]
aa  ha

$ ( LC_ALL=; LC_COLLATE=C; ls [a-z]*[^A-Z] )
a123e  aa  ah  ha  hh

Oder, besser, es ist wahrscheinlich vorzuziehen, die Gebietsschemaeinstellungen nicht zu ändern und die entsprechenden Klassen zu verwenden: [:lower:]anstelle von [a-z]und [:upper:]anstelle von [A-Z].

$ ls [[:lower:]]*[^[:upper:]]
a123e  aa  ah  ha  hh

Oder verwenden Sie die globasciirangesOption von bash :

$ shopt -s globasciiranges
$ ls [a-z]*[^A-Z]
a123e  aa  ah  ha  hh

$ shopt -u globasciiranges
$ ls [a-z]*[^A-Z]
aa  ha
xhienne
quelle
@heemayl, no LC_ALL=C ls [a-z]*[^A-Z]würde nur das lsGebietsschema beeinflussen, nicht das Gebietsschema, das von der Shell verwendet wird, um den Glob zu erweitern oder diese Befehlszeile zu analysieren.
Stéphane Chazelas
Sie müssen nicht exportieren, LC_xxxdamit es auf den Glob angewendet wird, aber es wäre vorzuziehen, damit ls das gleiche Gebietsschema erhält.
Stéphane Chazelas
1
Beachten Sie, dass in einer Gegend , in der charset ist GB18030 zum Beispiel mit der LC_ALL = C Ansatz wäre es nicht auf einer Datei mit dem Namen Übereinstimmen test-鏏zum Beispiel , weil , sobald Sie das charset zu dem dem C locale ändern, wird <0xe7>A. IOW, wenn Sie LC_CTYPE ändern, erhalten Sie unterschiedliche Zeichen.
Stéphane Chazelas
1
Beachten Sie, dass ich vermute, dass [AZ] im Gebietsschema des OP mehr als AbBcC ... zZ abdeckt. Wahrscheinlich hat auch é, Á(aber wahrscheinlich nicht Ź). IOW [A-Z]macht die Verwendung außerhalb des Gebietsschemas C wenig Sinn.
Stéphane Chazelas
@ StéphaneChazelas Vielen Dank für Ihr hervorragendes Feedback. Antwort aktualisiert. Ich glaube, ich habe alles berücksichtigt.
Xhienne