Як змінити файл на місці за допомогою 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над тимчасовим файлом, а не над оригінальним файлом) гарантує, що метадані файлу (дозволи та права власності) на вихідний файл не змінюються.


4

Спробуйте це.

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • перенаправити вихід у тимчасовий файл.
  • потім перемістіть вміст тимчасового файлу у вихідний файл.

1
Якщо ви подивитесь на вихідний код awk inplace, це саме те, що він робить: створює тимчасовий файл, перенаправляє туди stdout і в кінці перейменовує його у вхідний файл.
chx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.