Mengapa [az] asterisk cocok dengan angka?


13

Saya memiliki 3 direktori di jalur saat ini.

$ls
a_0db_data  a_clean_0db_data  a_clean_data
$ls a_*_data
a_0db_data:

a_clean_0db_data:

a_clean_data:

$ls a_[a-z]*_data
a_clean_0db_data:

a_clean_data:

Saya berharap perintah terakhir hanya cocok a_clean_data. Mengapa itu juga cocok dengan yang mengandung 0?

bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

2
Lihat pertanyaan ini untuk lebih lanjut tentang perbedaan antara ekspresi reguler dan gumpalan.
— terdon

4
Jadi fakta yang a_*_datacocok dengan `semua file ini tidak mengejutkan Anda?
— Cthulhu

@ Cthulhu Anda menangkap saya!
— user13107

Jawaban:


29

Bagian [a-z]ini tidak cocok dengan nomor tersebut; itu adalah *. Anda mungkin membingungkan shell globbing dan ekspresi reguler .

Alat seperti grepmenerima berbagai rasa regex ( dasar secara default, -Euntuk extended, -Puntuk Perl regex )

Misalnya ( -vmembalikkan pertandingan)

$ ls a_[a-z]*_data | grep -v "[0-9]"
a_clean_data

Jika Anda ingin menggunakan bash regex, berikut adalah contoh tentang cara menguji apakah variabel $reftersebut bilangan bulat:

re='^[0-9]+$'
if ! [[ $ref =~ $re ]] ; then
  echo "error"
fi

Bagaimana cara menggunakan bash regex? (lihat tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html )
— user13107


21

Jadi masalahnya adalah: mengapa a_[a-z]*_datacocok a_clean_0db_data?

Ini dapat dipecah menjadi empat bagian:

  • a_cocok dengan awal a_clean_0db_data, meninggalkan clean_0db_datauntuk dicocokkan

  • [a-z]cocok dengan karakter apa pun dalam rentang a-z(mis. c), membiarkan lean_0db_datadicocokkan

  • * cocok dengan sejumlah karakter, mis lean_0db

  • _data cocok dengan trailing _data

Dalam ekspresi reguler, [a-z]*berarti sejumlah karakter (termasuk nol) dalam kisaran a..z , tetapi Anda berhadapan dengan shell globbing, bukan dengan ekspresi reguler.

Jika Anda ingin ekspresi reguler, beberapa findimplementasi memiliki -regexpredikat untuk itu:

find . -maxdepth 1 -regex "^.*/a_[a-z]*_data$"

The -maxdepthhanya di sini untuk membatasi pencarian hasil ke folder Anda berada di. The ekspresi reguler sesuai dengan seluruh nama file, karena itu saya telah menambahkan ^.*/untuk mencocokkan jalur-bagian


11

*dalam pola shell cocok dengan 0 atau lebih karakter. Tidak perlu bingung dengan *operator ekspresi reguler yang berarti 0 atau lebih dari atom sebelumnya .

Tidak ada padanan regexp *dalam pola dasar shell. Namun, berbagai shell memiliki ekstensi untuk itu.

  • kshmemiliki *(something):

    ls a_*([a-z])_data
  • Anda dapat memiliki hal yang sama bashdengan shopt -s extglobatau zshdengan setopt kshglob:

    shopt -s extglob
    ls a_*([a-z])_data
  • Dalam zshdengan extendedglobdiaktifkan, #setara dengan regexp *:

    setopt extendedglob
    ls a_[a-z]#_data
  • Di versi terbaru ksh93, Anda juga dapat menggunakan ekspresi reguler di gumpalan. Di sini dengan ekspresi reguler yang diperluas :

    ls ~(E:a_[a-z]*_data)

Perhatikan bahwa [a-z]cocok dengan berbagai hal tergantung pada lokal saat ini. Secara umum hanya cocok 26 ake zhuruf latin non-aksen di Clokal. Di tempat lain, umumnya lebih cocok, dan tidak selalu masuk akal. Untuk mencocokkan huruf di lokal Anda, Anda dapat memilih [[:alpha:]].


Bisakah Anda memberikan contoh yang [a-z]lebih cocok dengan 26 huruf yang cocok dengan bahasa C? Apa yang saya ingat dari ketika saya terakhir kali melihat ini, semua pengkodean praktis digunakan dalam varian Unix memiliki ISO-646 sebagai basis (kemudian 128 kode atas di mana digunakan secara berbeda, langsung untuk karakter dalam pengkodean seperti ISO-8859-X, digabungkan dalam pengkodean seperti UTF-8 atau keluarga EUC). Bahkan AIX tidak memiliki lokal EBCDIC (setidaknya tersedia untuk saya). Saya ingat berusaha menemukan apakah standar POSIX / UNIX menuntutnya, tetapi saya tidak ingat hasilnya.
— Pemrogram

1
@AProgrammer, itu independen terhadap pengkodean, yang didasarkan pada urutan sortir (LC_COLLATE). [a-z]umumnya menyertakan éatau í(tetapi tidak harus ź) di locales tempat charset memilikinya, apakah codepoint dalam pengkodean itu antara a dan z atau tidak. Hanya lokal C yang menjamin urutan sortir berdasarkan nilai codepoint. Lihat jawaban lain ini untuk lebih jelasnya.
— Stéphane Chazelas

Ok, yang saya lewatkan adalah bahwa jangkauan ditafsirkan sesuai dengan urutan pemeriksaan saat ini.
— Pemrogram
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.