Saya memiliki file yang memiliki banyak nama host yang berkorelasi dengan IP yang terlihat seperti ini:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Saya ingin terlihat seperti ini:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
Bagaimana saya bisa mengganti. (titik) dari kolom pertama dengan - (tanda hubung) untuk memudahkan pengurutan berdasarkan kolom kedua? Saya berpikir untuk menggunakan sed untuk mengganti titik sampai spasi pertama, atau mengganti setiap titik kecuali tiga titik terakhir, tapi saya kesulitan memahami regex dan sed. Saya dapat melakukan penggantian sederhana tetapi ini jauh di atas kepala saya!
Ini adalah bagian dari skrip yang lebih besar yang telah saya tulis di bash. Saya terjebak di bagian ini.
awk
Berdasarkan spesifikasi POSIXnawk
, maka semuaawk
implementasi modern seharusnya memilikinyagsub
. Pada Solaris, Anda mungkin perlu/usr/xpg4/bin/awk
ataunawk
.Jika Anda perlu melakukan pergantian pada bidang pertama, yang terbaik adalah menggunakan solusi awk Rahul tetapi berhati-hatilah karena itu dapat mempengaruhi spasi (bidang ditulis ulang dengan satu ruang di antaranya).
Anda dapat menghindarinya dengan menulisnya sebagai gantinya:
The
-p
berarti bendera "membaca file baris masukan demi baris dan mencetak setiap baris setelah menerapkan script yang diberikan oleh-e
". Kemudian, gantikan (s|pattern|replacement|
) urutan pertama karakter non-spasi (\S+
) dengan pola yang cocok ($&
) setelah mengganti semua.
dengan-
. Caranya adalah dengan menggunakan dis|||e
manae
operator akan mengevaluasi ekspresi sebagai pengganti. Jadi, Anda dapat memiliki satu pengganti (tr/./-/
) diterapkan pada kecocokan ($&
) dari yang sebelumnya (s|||e
).Jika Anda perlu mengganti setiap
.
dengan-
kecuali 3 yang terakhir, dengan GNUsed
dan dengan asumsi Anda memilikirev
perintah:sumber
/r
dapat bekerja).Sed bukan alat termudah untuk pekerjaan itu - lihat jawaban lain untuk alat yang lebih baik - tetapi itu bisa dilakukan.
Untuk mengganti
.
dengan-
hanya sampai ke ruang pertama, penggunaans
dalam satu lingkaran.(Perhatikan bahwa beberapa implementasi sed tidak mendukung komentar pada baris yang sama. GNU sed tidak.)
Untuk melakukan penggantian hingga ruang terakhir:
Teknik lain memanfaatkan ruang pegang sed. Simpan bit yang tidak ingin Anda modifikasi ke dalam ruang tunggu, lakukan pekerjaan Anda, lalu ingat ruang penyimpanan. Di sini, saya membagi garis di ruang terakhir dan mengganti titik dengan tanda hubung di bagian pertama.
sumber
Karena Rahul memberi Anda jawaban kanonik untuk kasus penggunaan Anda, saya pikir saya akan mencoba menjawab masalah tituler: mengganti semua kecuali kejadian x terakhir dari sebuah regex:
Kode di atas (diuji) tidak menganggap bahwa Anda memiliki bidang yang dipisahkan oleh ruang. Ini akan mengganti semua titik pada garis dengan tanda hubung kecuali 3 titik terakhir. Ganti
3
kode dalam sesuai keinginan Anda.sumber
Anda dapat menggunakan banyak alat berbeda untuk ini. Rahul Patil sudah memberi Anda
gawk
satu jadi di sini ada beberapa yang lain:perl
The
-a
penyebab beralih perl untuk jalur input secara otomatis split pada spasi dan menyimpan bidang yang dihasilkan ke dalam array@F
. Oleh karena itu, bidang pertama akan$F[0]
jadi kami mengganti (s///
) semua kemunculan.
dengan-
di bidang pertama dan kemudian mencetak seluruh larik.kulit
Di sini, loop sementara membaca file dan secara otomatis membelah pada spasi putih. Ini menciptakan dua bidang,
$first
dan$rest
. Konstruk${first//pattern/replacement}
menggantikan semua kejadianpattern
denganreplacement
.sumber
perlrun(1)
akan memberi tahu Anda bahwa-a
"mode autosplit", saya lebih suka menganggapnya sebagai "awk
mode": DSaya percaya ini sedikit lebih mudah dibaca daripada regex jahat besar. Pada dasarnya saya hanya membagi garis menjadi dua bidang di spasi dan menggunakan sed pada bagian pertama.
Bergantung pada shell Anda, Anda juga bisa menggunakan $ {host //./-} alih-alih perintah sed.
sumber
Tanpa menggunakan
g
di akhir perintah Anda bisa melakukan ini ... Ini hanya akan menggantikan pola 1 kejadiansumber