Dapatkah seseorang menyarankan cara yang elegan untuk mencapai ini?
Memasukkan:
test instant ()
test instant ()
...
test instant () //total 1000 lines
output harus:
test instant1 ()
test instant2 ()
test instant1000()
Baris kosong ada di file input saya dan ada banyak file di bawah direktori yang sama yang harus saya proses sekaligus.
Saya mencoba ini untuk mengganti banyak file dalam direktori yang sama dan tidak berfungsi.
for file in ./*; do perl -i -000pe 's/instance$& . ++$n/ge' "$file"; done
kesalahan:
Substitution replacement not terminated at -e line 1.
Substitution replacement not terminated at -e line 1.
dan saya juga mencoba ini:
perl -i -pe 's/instant/$& . ++$n/ge' *.vs
Ini berhasil tetapi indeks terus bertambah dari satu ke file lain. Saya ingin mengatur ulang ke 1 setelah perubahan ke file baru. Ada saran bagus?
find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} +
berfungsi tetapi diganti semua file lain tidak boleh diganti. Saya lebih suka hanya mengganti file dengan *.txt
saja.
test instant ()
?Jawaban:
atau dengan GNU
awk
:Untuk mengedit file di tempat, tambahkan
-i
opsi keperl
:Atau secara rekursif:
Penjelasan
-p
adalah memproses input baris demi baris, mengevaluasi ekspresi yang diteruskan ke-e
untuk setiap baris dan mencetaknya. Untuk setiap baris, kami mengganti (menggunakans/re/repl/flags
operator)instant
untuk dirinya sendiri ($&
) dan nilai variabel yang ditambahkan++$n
. Theg
bendera adalah untuk membuat substitusi global (tidak hanya sekali), dane
sehingga penggantian ditafsirkan sebagai kode perl untuk e valuate (bukan string tetap).Untuk pengeditan di tempat di mana satu perl memproses lebih dari satu file, kami ingin
$n
mengatur ulang di setiap file. Sebagai gantinya, kami menggunakan$n{$ARGV}
(di mana$ARGV
file yang saat ini diproses).Yang
awk
pantas sedikit penjelasan.Kami menggunakan kemampuan GNU
awk
untuk memisahkan catatan pada string arbitrer (bahkan regexps). Dengan-vRS=instant
, kami mengatur s̲eparator r̲ecord keinstant
.RT
adalah variabel yang menyimpan apa yang cocok denganRS
, jadi biasanya,instant
kecuali untuk catatan terakhir di mana itu akan menjadi string kosong. Dalam input di atas record ($0
) dan terminator record (RT
) adalah ([$0|RT]
):Jadi yang perlu kita lakukan adalah memasukkan angka tambahan di awal setiap catatan kecuali yang pertama.
Itulah yang kami lakukan di atas. Untuk catatan pertama,
n
akan kosong. Kami mengatur ORS (the̲utput r̲ecord s̲eparator ) ke RT, sehinggaawk
tercetakn $0 RT
. Itu melakukannya pada ekspresi kedua (++n
) yang merupakan kondisi yang selalu bernilai true (angka bukan nol), dan karenanya tindakan default (pencetakan$0 ORS
) dilakukan untuk setiap catatan.sumber
sed
benar-benar bukan alat terbaik untuk pekerjaan itu, Anda menginginkan sesuatu dengan kemampuan skrip yang lebih baik. Berikut ini beberapa pilihan:perl
The
-p
berarti "mencetak setiap baris" setelah menerapkan script apapun yang diberikan dengan-e
. The-00
bergantian pada "mode ayat" sehingga catatan (baris) didefinisikan oleh baris berturut-turut (\n
) karakter, ini memungkinkan itu berurusan dengan garis spasi ganda dengan benar.$&
adalah pola terakhir yang cocok dan$.
merupakan nomor baris saat ini dari file input. Thee
dalams///e
memungkinkan saya untuk mengevaluasi ekspresi di operator substitusi.awk (ini mengasumsikan data Anda persis seperti yang ditunjukkan, dengan tiga bidang yang dipisahkan ruang)
Di sini, kami menambah
k
variabelk
hanya jika baris saat ini tidak kosong/./
dalam hal ini kami juga mencetak info yang diperlukan. Garis kosong dicetak apa adanya.berbagai kerang
Di sini, setiap baris input secara otomatis dibagi pada spasi putih dan bidang disimpan sebagai
$a
,$b
dan$c
. Kemudian, di dalam loop,$c
ditambah satu untuk setiap baris yang$a
tidak kosong dan nilainya saat ini dicetak di sebelah bidang kedua$b
,.CATATAN: semua solusi di atas menganggap bahwa semua baris dalam file memiliki format yang sama. Jika tidak, jawaban @ Stephane adalah caranya.
Untuk berurusan dengan banyak file, dan dengan asumsi bahwa Anda ingin melakukan ini untuk semua file di direktori saat ini, Anda dapat menggunakan ini:
HATI-HATI: Itu mengasumsikan nama file sederhana tanpa spasi, jika perlu berurusan dengan sesuatu yang lebih kompleks, gunakan (dengan asumsi
ksh93
,zsh
ataubash
):sumber
Jika Anda ingin menyelesaikan ini dengan
sed
Anda dapat menggunakan sesuatu seperti inibash
:atau solusi yang lebih portabel adalah:
sumber