Bagaimana cara mengganti file di tempat menggunakan awk? (seperti “sed -i”)

11

Saya memiliki sebuah awkskrip, new.awk:

 BEGIN { FS=OFS="," }
 NR==1 {
for (i=1; i<=NF; i++) {
    f[$i] = i
}
   } 
  NR > 1 {
 begSecs= mktime(gensub(/[":-]/," ","g",$(f["DateTime"])))
 endSecs = begSecs + $(f["TotalDuration"])
 $(f["CallEndTime"]) = strftime("%Y-%m-%d %H:%M:%S", endSecs)
 }
 { print }

Saya menyebut ini dalam shell

awk new.awk sample.csv

... tapi saya bisa melihat perubahan di terminal. Bagaimana cara membuat perubahan di tempat dalam file, seperti saat menggunakan sed -i?

mittu
sumber

Jawaban:

16

GNU awk(umumnya ditemukan pada sistem Linux), sejak versi 4.1.0, dapat menyertakan " awkpustaka sumber" dengan -iatau --includepada baris perintah. Salah satu pustaka sumber yang didistribusikan dengan GNU awkadalah yang disebut inplace:

$ cat file
hello
there
$ awk -i inplace '/hello/ { print "oh,", $0 }' file
$ cat file
oh, hello

Seperti yang Anda lihat, ini membuat output dari awkkode menggantikan file input. Pepatah baris theretidak disimpan karena tidak dihasilkan oleh program.

Dengan awkskrip dalam file, Anda akan menggunakannya seperti

awk -i inplace -f script.awk datafile

Jika awkvariabel INPLACE_SUFFIXdiatur ke string, maka perpustakaan akan membuat cadangan dari file asli dengan itu sebagai akhiran nama file.

awk -i inplace -v INPLACE_SUFFIX=.bak -f script.awk datafile

Jika Anda memiliki beberapa file input, maka setiap file dengan masing-masing di tempat diedit. Tetapi Anda dapat mematikan pengeditan di tempat untuk file (atau serangkaian file) dengan menggunakan inplace=0pada baris perintah sebelum file itu:

awk -i inplace -f script.awk file1 file2 inplace=0 file3 inplace=1 file4

Pada perintah di atas, file3tidak akan diedit di tempat.


Untuk "mengedit di tempat" yang lebih portabel dari satu file, gunakan

tmpfile=$(mktemp)
cp file "$tmpfile" &&
awk '...some program here...' "$tmpfile" >file
rm "$tmpfile"

Ini akan menyalin file input ke lokasi sementara, lalu menerapkan awkkode pada file sementara saat mengarahkan ke nama file asli.

Melakukan operasi dalam urutan ini (berjalan awkpada file sementara, bukan pada file asli) memastikan bahwa file meta-data (izin dan kepemilikan) dari file asli tidak diubah.

Kusalananda
sumber
4

Coba ini.

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • redirect output ke file temp.
  • kemudian pindahkan konten file temp ke file asli.
Siva
sumber
1
Jika Anda melihat kode sumber ink awk ini persis seperti apa yang dilakukannya: membuat file sementara, mengarahkan ulang stdout ke sana dan pada akhirnya mengganti nama file tersebut menjadi file input.
chx