Bagaimana cara mencari dan mengganti beberapa jarum dengan satu kata melalui satu ekspresi?

8

Asumsikan Anda memiliki file teks:

foo fnord bar
bizz foo poit

Dan sekarang saya ingin mengganti "foo" dan "bar" menjadi "narf".

Saya tahu saya bisa menggunakan:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

Namun saya ingin bekerja dengan operator-OR yang memberi tahu regex agar mencocokkan kedua jarum melalui satu ekspresi.

Memukul beberapa manual saya kira pipa harus sesuai dengan kebutuhan saya tetapi saya mencoba

sed -e 's/foo|bar/narf/g' -i fileName

dan itu tidak berhasil dan bahkan tidak membuat kesalahan.

Apa yang saya lakukan salah di sini?

k0pernikus
sumber

Jawaban:

10

Gunakan -ropsi untuk sintaks regexp tambahan:

sed -r -e 's/foo|bar/narf/g'

Jika tidak, lepas dari disjungsi sebagai \|:

sed -e 's/foo\|bar/narf/g'
Stéphane Gimenez
sumber
6

Ada banyak variasi pada sintaks ekspresi reguler . Alat pertama di dunia unix yang memiliki ekspresi reguler tidak memiliki kemampuan penuh ekspresi reguler, hanya set karakter ( […]dan .), pengulangan ( *) dan jangkar baris ( ^dan $). Ekspresi reguler dasar hanya memiliki operator ini. Sed adalah alat jadul dan menggunakan regexps dasar.

Banyak implementasi sed memiliki ekstensi untuk pencocokan regexp penuh. Karena karakter |singkatan sendiri, Anda perlu menggunakan \|untuk pergantian, dan sama \(dan \)untuk mengelompokkan. Perhatikan bahwa standar POSIX tidak mengamanatkan yang \|didukung dalam ekspresi reguler dasar , dan beberapa sistem (misalnya OpenBSD ) tidak memilikinya.

Beberapa versi sed memiliki opsi untuk beralih ke ekspresi reguler yang diperluas , di mana (…)digunakan untuk pengelompokan dan |untuk pergantian. Dengan sed GNU (yaitu di Linux atau Cygwin) atau Busybox , berikan -ropsi. Pada FreeBSD atau OSX , berikan -Eopsi.

Jika sed Anda tidak memiliki pergantian, Anda dapat menelepon awksaja. Ini diamanatkan oleh POSIX , tetapi sedikit bertele-tele untuk tugas ini, dan itu tidak mendukung referensi.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

Omong-omong, hanya GNU dan Busybox yang mendukung penggantian file di tempat. Versi awk dan sed lainnya tidak. Lihat Bisakah saya membuat `cut` mengubah file pada tempatnya?

Jika Anda memiliki Perl, sering berguna dalam cara satu-alat-tidak-semua untuk pemrosesan teks satu-liner. Sebagian besar dari apa yang mudah dalam sed, awk, dan sisanya tidak jauh lebih sulit di Perl, dan Anda dapat belajar satu alat (jika rumit).

perl -i -pe 's/foo|bar/narf/g' fileName
Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc '%s/\vPA|QU/RO/g|x' file
  1. % pilih semua baris

  2. s pengganti

  3. \v nyalakan sihir

  4. g ganti global

  5. x Simpan dan tutup

Steven Penny
sumber