Saya telah melihat contoh ini:
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
Yang mengikuti sintaks ini: ${variable//pattern/replacement}
Sayangnya, pattern
bidang tersebut tampaknya tidak mendukung sintaksis regex penuh (jika saya menggunakan .
atau \s
, misalnya, mencoba mencocokkan karakter literal).
Bagaimana saya bisa mencari / mengganti string menggunakan sintaks regex penuh?
\s
bukan bagian dari sintaks ekspresi reguler standar yang didefinisikan POSIX (baik BRE atau ERE); itu adalah ekstensi PCRE, dan sebagian besar tidak tersedia dari shell.[[:space:]]
adalah padanan yang lebih universal.\s
dapat diganti oleh[[:space:]]
, dengan cara,.
oleh?
, dan ekstensi extglob ke bahasa pola dasar shell dapat digunakan untuk hal-hal seperti subkelompok opsional, kelompok berulang, dan sejenisnya.Jawaban:
Gunakan sed :
Perhatikan bahwa proses selanjutnya
-e
diproses secara berurutan. Juga,g
tanda untuk ekspresi akan cocok dengan semua kemunculan dalam input.Anda juga dapat memilih alat favorit Anda menggunakan metode ini, yaitu perl, awk, misalnya:
Ini memungkinkan Anda melakukan lebih banyak pertandingan kreatif ... Misalnya, dalam snip di atas, penggantian numerik tidak akan digunakan kecuali ada kecocokan pada ekspresi pertama (karena
and
evaluasi malas ). Dan tentu saja, Anda memiliki dukungan bahasa penuh dari Perl untuk melakukan penawaran Anda ...sumber
sed
atau alat eksternal lainnya mahal karena waktu proses inisialisasi. Saya terutama mencari solusi all-bash, karena saya menemukan menggunakan pengganti bash menjadi lebih dari 3x lebih cepat daripada memanggilsed
setiap item di loop saya.Ini sebenarnya bisa dilakukan dalam bash murni:
... menghasilkan ...
sumber
=~
adalah kuncinya. Tapi agak kikuk, mengingat penugasan kembali dalam lingkaran. Solusi @jheddings 2 tahun sebelumnya adalah pilihan lain yang bagus - memanggil sed atau perl).sed
atauperl
masuk akal, jika menggunakan setiap doa untuk memproses lebih dari satu baris input. Meminta alat semacam itu di bagian dalam loop, sebagai lawan menggunakan loop untuk memproses aliran outputnya, adalah hal yang bodoh.$match
bukan$BASH_REMATCH
. (Anda dapat membuatnya berperilaku seperti bashsetopt bash_rematch
.)Contoh-contoh ini juga bekerja di bash tidak perlu menggunakan sed:
Anda juga dapat menggunakan ekspresi braket kelas karakter
keluaran
Apa yang ingin diketahui @Lanaru, jika saya memahami pertanyaan dengan benar, adalah mengapa ekstensi "penuh" atau PCRE
\s\S\w\W\d\D
dll tidak berfungsi sebagaimana didukung dalam php ruby python dll. Ekstensi ini berasal dari ekspresi reguler yang kompatibel dengan Perl (kompatibel dengan PCRE) dan mungkin tidak kompatibel dengan bentuk reguler ekspresi berbasis shell lainnya.Ini tidak berfungsi:
output dengan semua karakter "d" literal dihapus
tetapi yang berikut ini berfungsi seperti yang diharapkan
keluaran
Berharap itu menjelaskan hal-hal sedikit lebih banyak tetapi jika Anda belum bingung mengapa tidak Anda coba ini pada Mac OS X yang memiliki flag REG_ENHANCED diaktifkan:
Pada sebagian besar rasa * nix Anda hanya akan melihat output berikut:
nJoy!
sumber
${foo//$bar/$baz}
adalah tidak POSIX.2 BRE atau sintaks ERE - itu fnmatch () - gaya pola yang cocok.${hello//[[:digit:]]/}
karya, jika kita ingin memfilter hanya digit yang didahului oleh surato
,${hello//o[[:digit:]]*}
akan memiliki perilaku yang sama sekali berbeda dari yang diharapkan (karena dalam pola fnmatch,*
cocok dengan semua karakter, daripada memodifikasi item segera sebelum menjadi 0 atau lebih).[0-9]
atau[[:digit:]]
Jika Anda melakukan panggilan berulang dan mementingkan kinerja, Tes ini mengungkapkan metode BASH ~ 15x lebih cepat daripada melakukan forking dan kemungkinan proses eksternal lainnya.
sumber
Gunakan
[[:digit:]]
(perhatikan tanda kurung ganda) sebagai polanya:Hanya ingin meringkas jawaban (terutama @ nickl-'s https://stackoverflow.com/a/22261334/2916086 ).
sumber
Saya tahu ini adalah utas kuno, tetapi ini adalah hit pertama saya di Google, dan saya ingin membagikan yang berikut
resub
yang saya kumpulkan, yang menambahkan dukungan untuk beberapa backreferences $ 1, $ 2, dll. Referensi ...H / T ke @Charles Duffy re:
(.*)$match(.*)
sumber