Опция Awk inplace с оператором печати

В последней версии awk есть опция inplace которая может использоваться для выполнения операций, аналогичных опции sed -i. Однако я не могу заставить его работать с оператором print . Давайте посмотрим на мой пример. Содержимое тестового файла:

 11 aa 22 bb 
 root@localhost:~# cat test 11 aa 22 bb 

Если я не использую -i inplace , я могу получить желаемый результат в консоли.

 root@localhost:~# awk 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' test begin 111aa 22 bb end 

Когда я добавляю -i inplace , это то, что я получил.

 root@localhost:~# awk -i inplace 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' test begin end root@localhost:~# cat test 111aa 22 bb root@localhost:~# 

Как улучшить код и получить то, что я хочу?

Обновить


Моя версия awk – 4.1.1 .

 root@localhost:~# awk --version GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2-p3, GNU MP 6.0.0) Copyright (C) 1989, 1991-2014 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. root@localhost:~# 

Update2


 root@localhost:~# awk --version GNU Awk 4.1.2, API: 1.1 Copyright (C) 1989, 1991-2015 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. root@localhost:~# cat file 11 aa 22 bb root@localhost:~# awk 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' file begin 111aa 22 bb end root@localhost:~# awk -i inplace 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' file begin end root@localhost:~# cat file 111aa 22 bb root@localhost:~# 

Я думаю, вам нужно использовать BEGINFILE вместо BEGIN и ENDFILE вместо END для начала и конца для печати в файл.

По крайней мере, это работает на cygwin.

 Rob@Rob-PC /cygdrive/c/tmp $ awk --version GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2, GNU MP 6.0.0) Copyright (C) 1989, 1991-2014 Free Software Foundation. Rob@Rob-PC /cygdrive/c/tmp $ echo "11 aa 22 bb" > test Rob@Rob-PC /cygdrive/c/tmp $ awk -i inplace 'BEGINFILE{print "begin"} $1=="11"{print "111" $2; next} 1; ENDFILE{print "end" >> "test"}' test Rob@Rob-PC /cygdrive/c/tmp $ cat test begin 111aa 22 bb end 

Петли BEGIN и END запускаются до того, как файл будет обработан и после его обработки полностью. -i inplace имеет смысл только при обработке файла. Я не могу быть уверен, не проверяя исходный код, но поэтому представляется разумным, что BEGIN и END здесь не работают.

Как уже было предложено, для этого и существуют BEGINFILE и ENDFILE . Если они не работают в вашей настройке, вам придется использовать обходные пути. Хотя совпадение первой строки легко ( if(NR==1){print "begin"} ), то сопоставление последней строки немного сложнее. Некоторые трюки, которые вы можете использовать:

  1. Добавьте начальную и конечную строки, используя другой инструмент:

     perl -i -007ne 'print "begin\n${_}end\n"' file && awk -i inplace '$1=="11"{print "111" $2; next}1;' file 

    или

     printf "begin\n%s\nend" "$(cat file)" 
  2. Используйте awk для «begin» и добавьте «end» позже:

     awk -i inplace 'NR==1{print "begin"}$1=="11"{print "111" $2; next}1;' file && echo "end" >> file 
  3. Делайте все это с помощью инструмента, который может понять eof . Переключатель -a Perl заставляет его действовать как awk : он будет разделять поля на пробелы на @F . Просто как awk , переключатель -F позволяет установить разделитель полей. Переключатель -i редактирует файл на месте:

     perl -i -lane '$.==1 && print "begin"; eof && print "end"; if($F[0]=="11"){print "111$F[0] $F[1]"; next} print;' file