Dengan Terminal: Menggunakan Ungkapan Biasa II: Penggantian

Dalam Diri Saya artikel sebelumnya Saya telah memberitahu anda pada tahap asas bagaimana setiap watak khas ungkapan biasa yang paling banyak berfungsi. Dengan ungkapan biasa ini adalah mungkin untuk melakukan pencarian yang kompleks dalam fail teks atau dalam output perintah lain. Dalam artikel ini saya akan menerangkan bagaimana menggunakan perintah sed untuk mencari dan mengganti teks dengan cara yang jauh lebih kuat daripada sekadar menukar satu teks untuk teks yang lain.

Sedikit lebih banyak mengenai arahan grep

Sebelum saya mula bercakap mengenai sed, saya ingin mengulas lebih sedikit mengenai perintah grep untuk menyelesaikan apa yang telah dijelaskan dalam artikel sebelumnya sedikit. Semua yang akan saya sampaikan juga akan relevan dengan yang ini. Nanti kita akan melihat hubungan antara ini dan carian.

Menggabungkan ungkapan biasa

Banyak watak khas yang telah saya bicarakan dalam artikel sebelumnya dapat digabungkan, tidak hanya dengan watak lain, tetapi dengan ungkapan biasa. Cara untuk melakukannya adalah dengan menggunakan tanda kurung untuk membentuk subekspresi. Mari kita lihat contohnya. Mari mulakan dengan memuat turun teks yang boleh kita gunakan untuk ujian. Ini adalah senarai frasa. Untuk itu kita akan menggunakan arahan berikut:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Ini akan meninggalkan anda dalam direktori tempat anda melancarkan fail dengan nama "frasa." Anda boleh membukanya untuk melihat dan ketawa kecil. 

Sekarang mari kita anggap bahawa kita ingin mencari frasa yang mempunyai tepat 6 perkataan. Kesukarannya adalah dalam membentuk ungkapan biasa yang sesuai dengan setiap perkataan. Kata adalah urutan huruf, baik huruf besar atau huruf kecil, yang akan menjadi seperti '[a-zA-Z]+', tetapi anda juga harus menentukan bahawa huruf-huruf ini harus dipisahkan oleh aksara lain daripada huruf, yang seperti itu '[a-zA-Z]+[^a-zA-Z]+'. Mari kita ingat: "^" sebagai watak pertama di dalam tanda kurung menunjukkan bahawa kita ingin memadankan dengan watak yang tidak berada dalam julat dan "+" menunjukkan 1 atau lebih watak.

Kami sudah mempunyai ungkapan biasa yang dapat memadankan kata. Untuk memasangkannya dengan 6, ia harus diulang 6 kali. Untuk itu kami menggunakan kunci, tetapi tidak berguna untuk meletakkan '[a-zA-Z]+[^a-zA-Z]+{6}', kerana 6 akan mengulangi bahagian terakhir ungkapan biasa dan apa yang kita mahukan adalah mengulang semuanya, jadi apa yang harus anda masukkan adalah: '([a-zA-Z]+[^a-zA-Z]+){6}'. Dengan tanda kurung kita membentuk subekspresi dan dengan pendakap kita mengulanginya 6 kali. Sekarang anda hanya perlu menambahkan "^" di depan dan "$" di belakang untuk memadankan keseluruhan baris. Perintahnya adalah seperti berikut:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

Dan hasilnya adalah apa yang kita mahukan:

Ia lebih dinyanyikan daripada Macarena. Anda lebih berjaya daripada Luis Aguilé. Anda mempunyai budaya yang lebih sedikit daripada batu. Anda tahu lebih banyak bahasa daripada Cañita Brava. Dia mempunyai lebih banyak kerutan daripada Tutan Khamón. Anda kurang tahu daripada Rambo mengenai penjagaan anak.

Perhatikan bahawa kita meletakkan parameter -E kerana kita ingin menggunakan ungkapan biasa diperpanjang untuk membuat "+" berfungsi. Sekiranya kita menggunakan yang asas, kita harus melepaskan tanda kurung dan pendakap.

Rujukan belakang atau rujukan balik

Sekiranya anda memasang pemeriksa ejaan, anda mungkin akan mempunyai senarai perkataan /usr/share/dict/words. Sekiranya tidak, anda boleh memasangnya secara lengkung dengan:

sudo pacman -S words

Atau dalam debian dengan:

sudo aptitude install dictionaries-common

Sekiranya anda mahu, anda boleh melihat fail tersebut untuk melihat perkataan apa yang ada. Ini sebenarnya adalah pautan ke fail perkataan untuk bahasa pengedar anda. Anda boleh memasang beberapa fail perkataan pada masa yang sama.

Kami akan menggunakan fail itu. Ternyata kami sangat ingin tahu semua palindromes tujuh huruf di luar sana. Bagi mereka yang tidak tahu: Palindrome adalah kata capicúa, iaitu, ia dapat dibaca dari kiri ke kanan dan juga dari kanan ke kiri. Mari cuba arahan berikut:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Ia kelihatan agak pelik, bukan? Sekiranya kami mencubanya, hasilnya akan bergantung pada bahasa distro anda dan kata-kata dalam senarai anda, tetapi dalam kes saya, dengan bahasa Sepanyol, hasilnya adalah:

aniline aniline bergolek

Mari lihat bagaimana ungkapan biasa ini berfungsi.

Selain dari "^" dan "$", yang sudah kita ketahui, perkara pertama yang kita lihat di sebelah kiri adalah tiga kumpulan titik yang tertutup kurungan. Jangan bingung dengan bar di depan setiap kurungan. Mereka keluar dari tanda kurung kerana kita menggunakan ungkapan biasa, tetapi tidak mempunyai makna lain. Yang penting ialah kita meminta tiga aksara dengan titik, tetapi masing-masing titik itu ditutup dalam kurungan. Ini untuk menyelamatkan watak-watak yang sesuai dengan titik-titik itu sehingga mereka dapat dirujuk lagi dari ungkapan biasa. Ini adalah satu lagi penggunaan tanda kurung yang akan berguna kemudian dalam membuat penggantian.

Di sinilah ketiga-tiga nombor di bawah hadir dengan garis miring di hadapannya. Dalam kes ini, bar penting. Ini untuk menunjukkan bahawa nombor di bawah adalah rujukan belakang dan merujuk kepada salah satu tanda kurung sebelumnya. Contohnya: \ 1 merujuk kepada kurungan pertama, \ 2 hingga kedua, dan seterusnya.

Maksudnya, dengan ungkapan biasa yang kita masukkan, apa yang kita cari adalah semua kata yang dimulai dengan empat huruf dan kemudian mempunyai huruf yang sama dengan yang ketiga, yang lain sama dengan yang kedua dan yang lain itu sama dengan yang pertama. Hasilnya adalah palindrom tujuh huruf yang terdapat dalam senarai perkataan. Sama seperti yang kita mahukan.

Sekiranya kita menggunakan ungkapan biasa yang diperpanjang, kita tidak perlu melepaskan tanda kurung, tetapi dengan ungkapan biasa yang diperpanjang, rujukan balik tidak berfungsi di semua program kerana tidak standard. Namun, dengan grep mereka berfungsi, jadi itu mungkin cara lain untuk melakukan perkara yang sama. Anda boleh mencubanya jika anda mahu.

Ungkapan penggantian: arahan sed

Selain mencari, salah satu penggunaan ungkapan biasa yang terbaik adalah dengan mengganti teks yang kompleks. Untuk melakukan ini, salah satu cara untuk melakukannya adalah dengan perintah sed. Kekuatan arahan sed melampaui penggantian teks, tetapi di sini saya akan menggunakannya untuk itu. Sintaks yang akan saya gunakan dengan arahan ini adalah seperti berikut:

sed [-r] 's/REGEX/REPL/g' FICHERO

Atau juga:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Di mana REGEX akan menjadi ungkapan biasa carian dan REPL akan menjadi penggantinya. Perlu diingat bahawa perintah ini tidak benar-benar mengganti apa-apa dalam fail yang kita tunjukkan, tetapi apa yang dilakukannya menunjukkan kepada kita hasil penggantian di terminal, jadi jangan takut dengan perintah yang akan saya masukkan seterusnya. Tiada satu pun dari mereka yang akan mengubah fail pada sistem anda.

Mari kita mulakan dengan contoh mudah. Kita semua mempunyai pelbagai fail konfigurasi di direktori / etc yang biasanya mempunyai komen yang diawali dengan "#". Katakan kita mahu melihat salah satu fail ini tanpa komen. Sebagai contoh, saya akan melakukannya dengan fstab. Anda boleh mencuba dengan yang anda mahukan.

sed 's/#.*//g' /etc/fstab

Saya tidak akan meletakkan hasil perintah di sini kerana bergantung pada apa yang anda miliki di fstab anda, tetapi jika anda membandingkan output perintah dengan kandungan fail anda akan melihat bahawa semua komen telah hilang.

Dalam perintah ini ungkapan carian adalah «#.*", Itu adalah" # "diikuti oleh sebilangan watak, iaitu komen. Dan ungkapan penggantian, jika anda melihat dua bar berturut-turut, anda akan melihat bahawa tidak ada, jadi apa yang dilakukannya adalah menggantikan komen dengan apa-apa, iaitu menghapusnya. Lebih mustahil.

Sekarang kita akan melakukan sebaliknya. Anggaplah bahawa apa yang kita mahukan adalah mengulas semua baris fail. Mari cuba seperti ini:

sed 's/^/# /g' /etc/fstab

Anda akan melihat bahawa, dalam output arahan, semua baris bermula dengan tanda hash dan ruang kosong. Apa yang telah kami lakukan adalah menggantikan permulaan baris dengan «# «. Ini juga merupakan contoh yang cukup mudah di mana teks yang akan diganti selalu sama, tetapi sekarang kita akan menyukarkannya.

Rahmat penggantian adalah bahawa dalam ungkapan penggantian, anda boleh menggunakan rujukan balik seperti yang saya nyatakan sebelumnya. Mari kembali ke fail frasa yang kami muat turun pada awal artikel. Kami akan memasukkan tanda kurung semua huruf besar yang ada, tetapi kami akan melakukannya dengan arahan:

sed 's/\([A-Z]\)/(\1)/g' frases

Apa yang kita ada di sini adalah rujukan belakang dalam ungkapan penggantian yang merujuk kepada tanda kurung dalam ungkapan carian. Tanda kurung dalam ungkapan penggantian adalah tanda kurung normal. Dalam ungkapan penggantian mereka tidak memiliki arti khusus, mereka dinyatakan sebagaimana adanya. Hasilnya adalah bahawa semua huruf besar diganti dengan huruf yang sama, apa pun, dengan tanda kurung di sekitarnya.

Terdapat watak lain yang juga dapat digunakan dalam ekspresi penggantian, itu adalah "&" dan ia digantikan oleh semua teks yang dipadankan dengan ekspresi carian. Contoh dengan ini ialah meletakkan semua frasa dalam fail dalam tanda kutip. Ini dapat dicapai dengan arahan ini:

sed 's/.*/"&"/g' frases

Operasi perintah ini sangat serupa dengan yang sebelumnya, hanya sekarang yang kita ganti adalah keseluruhan baris dengan garis yang sama dengan tanda kutip di sekitarnya. Oleh kerana kita menggunakan "&", tidak perlu meletakkan tanda kurung.

Beberapa arahan berguna dengan ungkapan biasa

Berikut adalah beberapa arahan yang saya rasa berguna atau ingin tahu dan yang menggunakan ungkapan biasa. Dengan perintah ini, penggunaan ungkapan biasa jauh lebih baik daripada dengan contoh yang saya berikan setakat ini, tetapi nampaknya penting bagi saya untuk menjelaskan sesuatu tentang bagaimana ungkapan biasa berfungsi untuk memahaminya.

  • Tunjukkan bahagian halaman lelaki:

man bash | grep '^[A-Z][A-Z ]*$'

Sudah tentu, anda boleh menukar perintah bash kepada apa sahaja yang anda mahukan. Dan kemudian dari lelaki, anda boleh pergi terus ke bahagian yang menarik minat anda menggunakan, tentu saja, ungkapan biasa. Tekan «/» untuk mula mencari dan menulis «^ALIASES$»Untuk pergi ke bahagian ALIASES, misalnya. Saya rasa ini adalah penggunaan pertama yang saya buat untuk membuat ungkapan biasa beberapa tahun yang lalu. Menggerakkan beberapa halaman manual hampir mustahil tanpa muslihat seperti ini.

  • Tunjukkan nama semua pengguna mesin termasuk yang khas:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Tunjukkan nama pengguna, tetapi hanya yang mempunyai shell:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Ini benar-benar dapat dilakukan dengan satu ungkapan biasa, tetapi cara untuk melakukannya melampaui apa yang telah saya katakan kepada anda dalam artikel ini, jadi saya melakukannya dengan menggabungkan dua perintah.

  • Masukkan koma sebelum tiga digit terakhir dari semua nombor dalam fail nombor:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Ia hanya berfungsi dengan nombor hingga 6 digit, tetapi boleh dipanggil lebih dari sekali untuk meletakkan pemisah dalam kumpulan lain yang terdiri daripada tiga digit.

  •  Ekstrak semua alamat e-mel dari fail:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Pisahkan hari, bulan dan tahun dari semua tarikh yang muncul dalam fail:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Ketahui IP tempatan kami:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Ini juga dapat dilakukan dengan satu perintah sed, tetapi saya lebih baik memisahkannya menjadi grep dan sed untuk kesederhanaan.

Beberapa alamat berguna

Berikut adalah beberapa alamat yang mungkin berguna berkaitan dengan ungkapan biasa:

  • Perpustakaan ekspresi biasa: Ini adalah perpustakaan ekspresi biasa di mana anda dapat mencari ungkapan biasa yang berkaitan dengan topik yang menarik minat anda. Untuk mencari alamat web, ID atau apa sahaja.
  • RegExr: Pemeriksa ekspresi tetap dalam talian. Ini membolehkan anda memasukkan teks dan menerapkan ungkapan biasa padanya sama ada mencari atau mengganti. Ia memberikan maklumat mengenai ungkapan biasa dan anda mempunyai beberapa pilihan untuk mengubah tingkah lakunya.
  • Penguji Ungkapan Biasa: Ini adalah tambahan untuk firefox yang membolehkan memeriksa ungkapan biasa dari penyemak imbas.

Kesimpulan

Buat masa ini sahaja. Ungkapan biasa adalah kompleks tetapi berguna. Ia memerlukan masa untuk mempelajarinya, tetapi jika anda seperti saya, bermain dengan mereka akan kelihatan menyeronokkan dan, sedikit demi sedikit anda akan menguasainya. Ia adalah seluruh dunia. Akan ada banyak yang boleh dikatakan, mengenai pengukur malas, regex gaya PERL, multiline, dll. Dan kemudian setiap program mempunyai ciri dan variannya, jadi nasihat terbaik yang dapat saya berikan adalah dengan selalu melihat dokumentasi program yang anda gunakan setiap kali anda harus menulis ungkapan biasa dalam program baru.

Hey! …HEY! …BANGUN! …APA YANG ANDA SEMUA BUAT SEMASA TIDUR? 

Fuentes

Beberapa idea dan contoh untuk ungkapan biasa dalam artikel ini saya ambil dari sini:


Tambahkan sebagai sumber pilihan dalam Google