วิธีการเปลี่ยนไฟล์ในสถานที่โดยใช้ awk? (เช่นเดียวกับ“ sed -i”)


11

ฉันมีawkสคริปต์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 }

ฉันกำลังเรียกสิ่งนี้ในเปลือก

awk new.awk sample.csv

... แต่ฉันเห็นการเปลี่ยนแปลงในเครื่อง วิธีการเปลี่ยนแปลงแบบแทนที่ไฟล์เช่นเมื่อใช้sed -i?

คำตอบ:


16

GNU awk(พบได้ทั่วไปในระบบ Linux) ตั้งแต่รุ่น 4.1.0 สามารถรวม " awkซอร์สไลบรารี" กับ-iหรือ--includeบนบรรทัดคำสั่ง หนึ่งในไลบรารี่ต้นทางที่แจกจ่ายกับ GNU awkนั้นเรียกว่าinplace:

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

อย่างที่คุณเห็นสิ่งนี้ทำให้การส่งออกของawkรหัสแทนที่ไฟล์อินพุต บรรทัดที่พูดthereไม่ได้ถูกเก็บไว้เนื่องจากไม่ได้แสดงผลลัพธ์โดยโปรแกรม

ด้วยawkสคริปต์ในไฟล์คุณจะใช้มันเหมือน

awk -i inplace -f script.awk datafile

หากawkตัวแปรINPLACE_SUFFIXถูกตั้งค่าเป็นสตริงไลบรารีจะทำการสำรองข้อมูลของไฟล์ต้นฉบับโดยใช้ส่วนต่อท้ายเป็นชื่อไฟล์

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

หากคุณมีไฟล์อินพุตหลายไฟล์แต่ละไฟล์จะถูกแก้ไขแบบแทนที่ทีละไฟล์ แต่คุณสามารถปิดการแก้ไขแบบแทนไฟล์ (หรือชุดไฟล์) โดยใช้inplace=0บนบรรทัดคำสั่งหน้าไฟล์นั้น:

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

ในคำสั่งข้างต้นfile3จะไม่ถูกแก้ไขในสถานที่


สำหรับการพกพา "แก้ไขแบบแทนที่" ของไฟล์เดียวให้ใช้

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

สิ่งนี้จะคัดลอกไฟล์อินพุตไปยังตำแหน่งชั่วคราวจากนั้นใช้awkโค้ดบนไฟล์ชั่วคราวในขณะที่เปลี่ยนเส้นทางไปยังชื่อไฟล์ดั้งเดิม

การดำเนินการตามลำดับนี้ (ทำงานawkกับไฟล์ชั่วคราวไม่ใช่ไฟล์ต้นฉบับ) ทำให้แน่ใจได้ว่าไฟล์ meta-data (สิทธิ์และความเป็นเจ้าของ) ของไฟล์ต้นฉบับไม่ได้ถูกแก้ไข


4

ลองสิ่งนี้

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • เปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์ชั่วคราว
  • จากนั้นย้ายเนื้อหาของไฟล์ temp ไปยังไฟล์ต้นฉบับ

1
หากคุณดูซอร์สโค้ด ink ของ awk นี่คือสิ่งที่มันทำ: สร้างไฟล์ชั่วคราวเปลี่ยนเส้นทาง stdout ที่นั่นและในตอนท้ายจะเปลี่ยนชื่อเป็นไฟล์อินพุต
chx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.