Saya ingin melakukan pencocokan pola non-serakah (ekspresi reguler) awk
. Berikut ini sebuah contoh:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
Apakah mungkin untuk menulis ekspresi reguler yang memilih string yang lebih pendek?
@article{gjn,
bukannya string panjang ini ?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Saya ingin mendapatkan hasil ini:
Author = {Grzegorz J. Nalepa},
Saya punya contoh lain:
gema " , artikel {gjn, Penulis = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); cetak} ' ↑ ↑ ^^^^^
Perhatikan bahwa saya mengubah @
karakter menjadi koma ( ,
) karakter di posisi pertama dari string input dan ekspresi reguler (dan juga berubah .*
menjadi [^,]*
). Apakah mungkin untuk menulis ekspresi reguler yang memilih string yang lebih pendek?
, Author = {Grzegorz J. Nalepa},
bukannya string yang lebih panjang ?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Saya ingin mendapatkan hasil ini:
,article{gjn
awk
regular-expression
sekarang1
sumber
sumber
Author
mengikuti koma dan spasi, diikuti oleh spasi putih diikuti oleh=
diikuti oleh spasi putih diikuti oleh{
diikuti oleh non-}
diikuti oleh}
, meskipun ini membutuhkan (antara lain) bahwa Anda tidak bisa bersarang{}
di dalam= { ... }
bagian.Jawaban:
Jika Anda ingin memilih
@
dan hingga yang pertama,
setelah itu, Anda harus menentukannya sebagai@[^,]*,
Yang
@
diikuti oleh nomor (*
) dari non-koma ([^,]
) diikuti oleh koma (,
).Pendekatan itu berfungsi sebagai padanan
@.*?,
, tetapi tidak untuk hal-hal seperti@.*?string
, di situlah yang dicari lebih dari satu karakter. Meniadakan karakter itu mudah, tetapi meniadakan string dalam regexps jauh lebih sulit .Pendekatan yang berbeda adalah dengan pra-proses input Anda untuk mengganti atau menambahkan
string
dengan karakter yang sebaliknya tidak terjadi pada input Anda:Jika Anda tidak dapat menjamin bahwa input tidak akan mengandung karakter pengganti Anda (di
\1
atas), salah satu pendekatan adalah menggunakan mekanisme melarikan diri:Itu bekerja untuk
string
s tetap tetapi tidak untuk regexps sewenang-wenang seperti untuk setara@.*?foo.bar
.sumber
Sudah ada beberapa jawaban yang baik untuk mengatasi
awk
ketidakmampuan melakukan pertandingan yang tidak serakah, jadi saya memberikan beberapa informasi tentang cara alternatif untuk melakukannya menggunakan Perl Compatible Regular Expressions (PCRE). Perhatikan bahwaawk
skrip "cocok dan cetak" yang paling sederhana dapat dengan mudah diimplementasikan kembali denganperl
menggunakan-n
opsi baris perintah, dan skrip yang lebih kompleks dapat dikonversi dengan penerjemah Awk to Perl a2p .Perl memiliki operator non-serakah yang dapat digunakan dalam skrip Perl dan apa pun yang menggunakan PCRE. Misalnya, juga diterapkan dalam
-P
opsi GNU grep .PCRE tidak identik dengan ekspresi reguler Perl, tetapi sangat dekat. Ini adalah pilihan populer dari perpustakaan ekspresi reguler untuk banyak program, karena sangat cepat, dan peningkatan Perl untuk ekspresi reguler yang diperluas sangat berguna.
Dari halaman manual perlre (1) :
sumber
Ini adalah pos lama, tetapi informasi berikut mungkin bermanfaat bagi orang lain.
Ada cara, diakui kasar, untuk melakukan pencocokan RE serakah dalam awk. Ide dasarnya adalah menggunakan fungsi match (string, RE), dan secara progresif mengurangi ukuran string sampai match gagal, kira-kira seperti (belum teruji):
sumber
Untuk ekspresi umum, ini dapat digunakan sebagai pasangan yang tidak serakah:
Saya menggunakan ini berdasarkan jawaban @ JimMellander.
smatch
berperilaku sepertimatch
, kembali:sumber
Tidak ada cara di awk untuk melakukan pencocokan non-serakah. Anda mungkin bisa mendapatkan output yang diinginkan. Saran sch akan bekerja untuk baris itu. Jika Anda tidak dapat mengandalkan koma, tetapi "Penulis" selalu merupakan awal dari apa yang Anda inginkan, Anda bisa melakukan ini:
Jika jumlah karakter sebelum Penulis selalu sama, Anda bisa melakukan ini:
Anda hanya perlu tahu seperti apa data Anda di seluruh rangkaian.
sumber
Selalu ada cara. Masalah yang diberikan dapat diselesaikan dengan cukup mudah dengan menggunakan koma sebagai pemisah.
Ketika jumlah bidang bervariasi sesuatu yang sedikit lebih baik biasanya dibutuhkan. Dalam kasus seperti itu, menemukan kata-kata penghenti sering terbayar, karena Anda dapat memotong apa pun dari garis dengan menggunakannya. Dalam konteks contoh inilah yang saya maksud dengan kata-kata berhenti.
sumber
Saya tahu ini adalah pos lama. Tapi di sini ada sesuatu yang hanya menggunakan awk sebagai OP seperti yang diminta:
A = @ article {gjn2010jucs, Penulis = {Grzegorz J. Nalepa},
gema $ A | sub awk '(/ @ [^,] * /, "")'
Keluaran
:, Penulis = {Grzegorz J. Nalepa},
sumber