Сохраняйте изменения на месте с помощью awk

Я изучаю awk, и я хотел бы знать, есть ли возможность записать изменения в файл, похожие на sed, где я бы использовал параметр -i для сохранения изменений в файле.

Я понимаю, что я мог бы использовать перенаправление для записи изменений. Однако есть ли опция awk для этого?

Ответы

Ответ 1

В последнем выпуске GNU Awk (так как 4.1.0 выпущен), он имеет возможность "inplace" редактировать файл:

[...] Расширение "inplace", построенное с использованием нового средства, может использоваться для имитации функции GNU "sed -i". [...]

Пример использования:

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

Чтобы сохранить резервную копию:

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

Ответ 2

Если у вас нет GNU awk 4.1.0 или новее...

У вас не будет такой опции, как sed -i поэтому вместо этого сделайте:

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

Примечание: -i не волшебство, он также создает временный файл sed просто обрабатывает его для вас.


Начиная с GNU awk 4.1.0...

GNU awk добавил эту функциональность в версии 4.1.0 (выпущена 05.10.2013). Это не так просто, как просто дать -i как описано в выпущенных заметках:

Новая опция -i (из xgawk) используется для загрузки файлов библиотеки awk. Это отличается от -f тем, что первый неопциональный аргумент обрабатывается как скрипт.

Вам нужно использовать входящий в комплект inplace.awk файл inplace.awk чтобы правильно inplace.awk расширение, например:

$ cat file
123 abc
456 def
789 hij

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

$ cat file
123
456
789

Переменная INPLACE_SUFFIX может использоваться для указания расширения для файла резервной копии:

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

$ cat file
123
456
789

$ cat file.bak
123 abc
456 def
789 hij

Я рад, что эта функция была добавлена, но для меня реализация не очень прихотлива, так как сила исходит от краткости языка, и на месте -i inplace 8 символов слишком долго.

Вот ссылка на руководство по официальному слову.

Ответ 3

@sudo_O имеет правильный ответ .

Это не может работать:

someprocess < file > file

Оболочка выполняет перенаправления перед передачей управления некоторому процессу (redirections). Перенаправление > усекает файл до нулевого размера (перенаправление вывода). Поэтому, к тому времени, когда someprocess запускается и хочет прочитать из файла, для чтения нет данных.

Ответ 4

просто немного взломать, что работает

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

Ответ 5

Альтернативой является использование sponge:

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

Если вы замените '{print $0}' на ваши awk script и your_file на имя файла, который вы хотите изменить на месте.

sponge полностью поглощает ввод, прежде чем сохранять его в файл.

Ответ 6

Использование tee

 awk '{awk code}' file | tee file

команда tee выполняется и выполняется после завершения команды awk из-за |.

Ответ 7

Если вы хотите использовать awk-only без создания временного файла и использовать его с версией!= (gawk 4.1.0):

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

Ответ 8

следующее не будет работать

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

это должно работать

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