Bagaimana mengubah karakter pada baris tertentu tanpa pembatas dengan awk

0

Saya punya file, dan saya ingin mengubah satu karakter pada baris 400 hingga 600. Karakter tersebut merupakan karakter ke-22 pada setiap baris. Itu juga kolom ke-5, jadi saya mencoba yang berikut:

awk '{if (NR>=400 && NR <=600) $5="B"; print}' file.txt

Masalahnya adalah, antara setiap kolom ada jumlah ruang yang tepat yang bisa diganti oleh satu ruang saat saya melakukan ini. Bagaimana saya bisa mengubah satu karakter tanpa menyentuh karakter lain, termasuk pembatas, dalam rentang garis?

sodiumnitrate
sumber

Jawaban:

1

Cara yang elegan adalah memperlakukan setiap karakter sebagai bidang. Jika Anda mengatur FS ke string kosong, awk akan membaginya begitu saja. Kemudian Anda dapat mengatur bidang ke-22 sesuai keinginan Anda. Hanya ingat untuk mengatur OFS ke string kosong juga sehingga tidak ada spasi (OFS default) antara semua karakter dalam output.

awk -vFS="" -vOFS="" 'NR==400,NR==600 {$22="B"}; {print}'

Jelas, ini akan melakukan pemisahan yang tidak perlu pada garis di luar jangkauan. Kita bisa mengatur pemisah bidang sebelum garis 400 dan kembali setelah 600. Tapi mengapa terpecah sama sekali di sini ketika kita memiliki substr ()? Mari kita buat string dengan 21 karakter pertama + "B" + sisa baris asli untuk baris-baris penting.

awk  '{s=$0}; NR==400,NR==600 { s=substr($0,1,21) "B" substr($0,23)}; {print s}'

(Adalah mungkin untuk melakukannya tanpa s, hanya dengan menetapkan $ 0 nilai baru tetapi ketika kami menetapkan $ 0, itu dibagi lagi sesuai dengan aturan, dan tidak ada alasan untuk mengorbankan kecepatan untuk langkah itu sekarang.)

Gombai Sándor
sumber
0

Anda juga bisa menggunakannya sed:

sed -r '400,600s/(.{21}).(.*)/\1B\2/' file.txt
Michael Vehrs
sumber