Mengapa '[az] *' cocok dengan string non-abjad?

9

Saya punya file alphanumdengan dua baris ini:

123 abc
this is a line

Saya bingung mengapa, ketika saya menjalankan sed 's/[a-z]*/SUB/' alphanum, saya mendapatkan output berikut:

SUB123 abc
SUB is a line

Saya mengharapkan:

123 SUB
SUB is a line

Saya menemukan perbaikan (gunakan sed 's/[a-z][a-z]*/SUB/'saja), tapi saya tidak mengerti mengapa itu berhasil dan milik saya tidak.

Dapatkah kamu menolong?

Fakher Mokadem
sumber
@ Kamaraj, yang serupa, tetapi memiliki pola shell vs regex kebingungan di atas (dan jawabannya berkonsentrasi pada yang pertama, karena itulah yang digunakan di ls foo*sana). Tapi bagaimanapun, jika Anda menemukan pertanyaan yang merupakan duplikat, saya pikir Anda harus dapat menandai mereka juga.
ilkkachu
lihat regexr.com untuk visual langsung & jelaskan
RozzA
@RozzA Perhatikan bahwa situs web yang Anda tautkan mendukung Javascript dan Perl ekspresi reguler, bukan ekspresi reguler POSIX.
Kusalananda

Jawaban:

28

Pola [a-z]*cocok dengan nol atau lebih karakter dalam rentang ake z( karakter sebenarnya tergantung pada lokal saat ini). Ada nol karakter tersebut di awal string 123 abc(yaitu pola yang cocok), dan juga empat dari mereka di awal this is a line.

Jika Anda membutuhkan setidaknya satu kecocokan, gunakan [a-z][a-z]*atau [a-z]\{1,\}, atau aktifkan ekspresi reguler yang diperluas dengan sed -Edan gunakan [a-z]+.

Untuk memvisualisasikan di mana pola cocok, tambahkan tanda kurung di sekitar setiap pertandingan:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

Atau, untuk melihat semua kecocokan pada baris:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Bandingkan hasil terakhir itu dengan

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)
Kusalananda
sumber
7
Secara teknis [a-z]cocok dengan elemen penyusun yang dapat dibuat lebih dari satu karakter. Misalnya, di beberapa lokal Hongaria, [a-z]pertandingan padadzs
Stéphane Chazelas
12

Karena *cocok dengan nol atau lebih pengulangan dari atom sebelumnya, dan semua mesin regex mencoba menemukan kecocokan pertama. Ada substring persis nol huruf di awal string Anda, jadi di situlah cocok. Dalam kasus di mana string dimulai dengan huruf, *kecocokan sebanyak mungkin, tetapi ini sekunder untuk menemukan kecocokan paling kiri.

Pencocokan panjang nol dapat sedikit bermasalah, dan seperti yang Anda lihat, solusinya adalah mengubah pola sehingga membutuhkan setidaknya satu karakter. Dengan regex yang diperluas, Anda bisa +untuk itu:sed -E 's/[a-z]+/SUB/'

Untuk bersenang-senang, cobalah:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
ilkkachu
sumber