2013-05-13 18 views
79

Uczę się awk i chciałbym wiedzieć, czy istnieje opcja zapisu zmian w pliku, podobnie jak sed, gdzie chciałbym użyć opcji -i, aby zapisać zmiany w pliku.awk zapisać zmiany w miejscu

Rozumiem, że mogę użyć przekierowania do zapisywania zmian. Czy istnieje jednak możliwość wykonania tego w awk?

+0

Zobacz także http://serverfault.com/a/547331/313521 dla bardziej ogólnej odpowiedzi na "edytowanie pliku w miejscu z przekierowaniem". – Wildcard

Odpowiedz

68

W najnowszym GNU awk (od 4.1.0 released), ma możliwość "inplace" file editing:

[...] W "inplace" rozszerzenie, zbudowany przy użyciu nowego obiektu, może być używany do symulacji GNU "sed -i" funkcja. [...]

Przykład użycia:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3 

Aby zachować kopię zapasową:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") } 
> { print }' file1 file2 file3 
+1

@sudo_O - Dzięki za demonstrację "inplace". Wznowiona odpowiedź! – lind

+0

Wygląda na to, że opcja mogła zostać usunięta? W wersji 4.1.3 mam "-i includefile \t \t --include = includefile" –

+0

@Keith Miałem to samo pytanie. Po prostu wypróbowałem to i działa na moim 4.1.3. 'inplace' jest tak naprawdę biblioteką dołączoną do' gawk' zgodnie z [odpowiedź iiSeymoura] (http://stackoverflow.com/a/16529730/2877364), więc 'inplace' to coś, co może być zawarte jako' includefile'. – cxw

84

Chyba że masz GNU awk 4.1.0 lub nowszy ...

Nie ma takiej opcji jako opcji SED -i więc zamiast zrobić:

$ awk '{print $0}' file > tmp && mv tmp file 

Uwaga: -i nie jest magią, tworzy także tymczasowy plik sed po prostu go obsługuje.


Jak GNU awk 4.1.0 ...

GNU awk dodaje tę funkcjonalność w wersji 4.1.0 (wydany 05.10.2013). To nie jest tak prosto, jak tylko do przodu dając możliwość -i jak opisano w opublikowanych notach:

Nowa opcja -i (od xgawk) służy do ładowania plików bibliotecznych awk. Różni się od -f tym, że pierwszy argument nieoparty na liście jest traktowany jako skrypt.

Trzeba użyć dołączone inplace.awk zawierać plik, aby wywołać rozszerzenie właściwie tak:

$ cat file 
123 abc 
456 def 
789 hij 

$ gawk -i inplace '{print $1}' file 

$ cat file 
123 
456 
789 

Zmienna INPLACE_SUFFIX mogą być wykorzystane do określenia rozszerzenia dla pliku kopii zapasowej:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file 

$ cat file 
123 
456 
789 

$ cat file.bak 
123 abc 
456 def 
789 hij 

Cieszę się, że ta funkcja została dodana, ale dla mnie implementacja nie jest zbyt przerażająca, ponieważ moc jest ze zwięzłością języka, a -i inplace to 8 c znaki do długiego I.M.O.

Oto link do manual dla oficjalnego słowa.

11

@sudo_O ma prawo answer.

nie może działać:

someprocess <file> file 

Powłoka wykonuje przekierowania przed i przekazuje kontrolę nad do someprocess (redirections). Przekierowanie > spowoduje obcięcie pliku do rozmiaru zerowego (redirecting output). Dlatego do czasu uruchomienia procesu i odczytu z pliku nie ma danych do odczytu.

2

w przypadku chcesz rozwiązanie awk-tylko bez tworzenia pliku tymczasowego i użytkowej z wersja! = (gawk 4.1.0):

awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file 
+0

Ale czy buforuje cały plik do pamięci? Rozważ plik 20 GB. –

5

tylko mały hack, który działa

echo "$(awk '{awk code}' file)" > file 
+5

Nie działa: nowe linie. – Lloeki

+1

@Lloeki dzięki, poprawiłem odpowiedź :) –

3

następujące nie będzie działać

echo $(awk '{awk code}' file) > file 

to powinno działać

echo "$(awk '{awk code}' file)" > file 
3

Alternatywą jest użycie sponge:

awk '{print $0}' your_file | sponge your_file 

Gdzie wymienić '{print $0}' przez Ciebie r awk script i your_file przez nazwę pliku, który chcesz edytować.

sponge pochłania całkowicie wejście przed zapisaniem go w pliku.

0

Korzystanie tee

awk '{awk code}' file | tee file 

polecenia tee odbywać i realizowane po komenda awk zakończeniu powodu |.