Mengapa beberapa perintah regex memiliki interpretasi '\' yang berlawanan dengan berbagai karakter?

10

Ambil, misalnya, perintah ini:

find . -regex ".*\.\(cpp\|h\)"

Ini akan menemukan semua file .h dan .cpp di direktori Anda. Karakter periode '.' dalam ekspresi reguler biasanya berarti "karakter apa saja". Untuk membuatnya hanya cocok dengan periode aktual, Anda harus menghindarinya menggunakan karakter backslash '\'.

Dalam hal ini, mengingat karakter dengan makna khusus, Anda harus menghindarinya untuk mendapatkan karakter aktual yang diwakilinya.

Sekarang, ambil tanda kurung dan bilah "atau", masing-masing menjadi karakter '(', ')', dan '|'. Ini juga memiliki makna khusus, yang digunakan untuk mengelompokkan ekspresi reguler. Namun, untuk mendapatkan makna khusus, karakter harus melarikan diri menggunakan garis miring terbalik! Tanpa garis miring terbalik, karakter memiliki makna karakter aktual yang diwakilinya.

Mengapa '.' diperlakukan secara berbeda dari '(', ')', dan '|'?

Cory Klein
sumber

Jawaban:

12

Jawabannya benar-benar "hanya karena". Ada sejumlah besar sintaks ekspresi reguler yang berbeda, dan meskipun mereka memiliki tampilan yang sama dan biasanya dasarnya sama, mereka berbeda-beda dalam rinciannya.

Secara historis, setiap alat memiliki implementasi baru sendiri, melakukan apa pun yang menurut penulis terbaik. Ada keseimbangan antara membuat karakter spesial dengan dan tanpa melarikan diri - terlalu banyak karakter yang "spesial secara alami" dan Anda akhirnya harus melarikan diri sepanjang waktu hanya untuk mencocokkannya; atau, sebaliknya, Anda akhirnya membutuhkan sekelompok lolos untuk menggunakan sintaks regex umum seperti () pengelompokan. Dan setiap orang yang menulis sebuah program memutuskan bagaimana melakukannya berdasarkan pada kebutuhan yang cocok dengan program mereka, pada apa yang mereka rasakan adalah pendekatan yang tepat, dan pada fase bulan.

Ada upaya standardisasi dari POSIX, yang mendefinisikan " ekspresi reguler dasar " dan " ekspresi reguler yang diperluas ". Awesomely, ini bekerja mundur satu sama lain dalam hal \- kadang - kadang , tetapi tidak dengan konsistensi yang sempurna.

Ekspresi reguler Perl telah menjadi standar defacto lain, karena dua alasan: pertama, mereka sangat fleksibel dan kuat, dan kedua, mereka sebenarnya cukup waras , dengan konvensi seperti "\ selalu lolos dari karakter non-alfanumerik".

GNU Find memiliki -regextypeopsi, di mana Anda dapat mengubah sintaks ekspresi reguler yang digunakan. Sayangnya, "perl" bukanlah pilihan, setidaknya dalam versi find yang saya miliki. (Defaultnya, tidak mengejutkan dari GNU, "emacs", dan sintaks itu didokumentasikan di sini .)

mattdm
sumber