Bash Globbing tidak seperti yang diharapkan


8

Ini adalah pertanyaan PR:

Cocokkan semua nama file dengan 2 karakter atau lebih yang dimulai dengan huruf kecil, tetapi jangan diakhiri dengan huruf besar.

Saya tidak mengerti mengapa solusi saya tidak berfungsi.

Jadi saya mengeksekusi di bawah ini:

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

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

Keluaran:

aa  ha

Pertanyaan saya: Mengapa tidak cocok dengan "ah", "hh", atau "a123e"?


Bekerja untuk saya dengan benar di bawah mkshshell, tetapi tidak bash --posix, jadi pasti ada beberapa aturan khusus untuk bash`
Sergiy Kolodyazhnyy

@Erg, perhatikan bahwa perilaku untuk [AZ] tidak ditentukan oleh POSIX kecuali di lokal C. mkshseperti zsh's [A-Z]tidak cocok pada Émisalnya. Pertandingan ksh93 [A-Z]aktif Étetapi tidak aktif h.
Stéphane Chazelas

Jawaban:


9

Ini adalah masalah lokal . Di lokal Anda, [A-Z]perluas sesuatu seperti [AbBcZ...zZ](ditambah mungkin yang lain seperti karakter beraksen), karena itu [^A-Z]sebenarnya berarti "file yang diakhiri dengan a" dalam contoh Anda (dan hanya dalam contoh Anda).

Jika Anda ingin menghindari kejutan seperti itu, salah satu caranya adalah mengatur LC_COLLATE=C karena pemeriksaan adalah bagian dari pengaturan lokal Anda yang bertanggung jawab atas urutan penyortiran. Juga, kosongkan LC_ALLjika sudah diatur, karena akan diutamakan.

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

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

Atau, lebih baik, mungkin lebih baik tidak mengubah pengaturan lokal Anda dan menggunakan kelas yang sesuai: [:lower:]alih- alih [a-z]dan [:upper:]bukannya [A-Z].

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

Atau gunakan globasciirangesopsi bash :

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

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

@ Heemayl, tidak LC_ALL=C ls [a-z]*[^A-Z]hanya akan mempengaruhi lslokal, bukan lokal yang digunakan oleh shell untuk memperluas glob atau mengurai baris perintah itu.
Stéphane Chazelas

Anda tidak perlu mengekspor LC_xxxagar dapat diterapkan ke glob, tetapi akan lebih disukai sehingga mendapatkan lokasi yang sama.
Stéphane Chazelas

1
Perhatikan bahwa di lokal di mana charset adalah GB18030 misalnya, dengan pendekatan LC_ALL = C, itu akan gagal untuk mencocokkan pada file yang dipanggil test-鏏misalnya karena setelah Anda mengubah charset ke yang dari lokal C, menjadi <0xe7>A. TKI, saat mengganti LC_CTYPE, Anda mendapatkan karakter yang berbeda.
Stéphane Chazelas

1
Perhatikan bahwa saya menduga [AZ] di lokal OP mencakup lebih dari AbBcC ... zZ. Mungkin juga memiliki é, Á(tapi mungkin tidak Ź). TKI, menggunakan [A-Z]sedikit tidak masuk akal di luar C locale.
Stéphane Chazelas

@ StéphaneChazelas Terima kasih atas umpan balik yang sangat baik. Jawaban diperbarui. Saya percaya saya memperhitungkan semuanya.
xhienne
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.