Назначение вывода системной команды переменной - PullRequest
45 голосов
/ 25 декабря 2009

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

Пример:

$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/}

Должен вызывать системную команду strip и вместо отправки вывода в оболочку должен присвоить вывод обратно $1 для дальнейшей обработки. Rignt сейчас, он отправляет вывод в оболочку и присваивает ретакод команды $1.

Ответы [ 5 ]

55 голосов
/ 25 декабря 2009

Примечание: Копроцесс специфичен для GNU awk.В любом случае, другой альтернативой является использование getline

cmd = "strip "$1
while ( ( cmd | getline result ) > 0 ) {
  print  result
} 
close(cmd)

Вызов close(cmd) не позволит awk выдать эту ошибку после ряда вызовов:

fatal: не удается открыть канал `…'(Слишком много открытых файлов)

27 голосов
/ 28 июля 2016

Для запуска системной команды в awk вы можете использовать system() или cmd | getline.

Я предпочитаю cmd | getline, потому что он позволяет вам перехватить значение в переменной:

$ awk 'BEGIN {"date" |  getline mydate; close("date"); print "returns", mydate}'
returns Thu Jul 28 10:16:55 CEST 2016

В общем, вы можете установить команду в переменную:

awk 'BEGIN {
       cmd = "date -j -f %s"
       cmd | getline mydate
       close(cmd)
     }'

Обратите внимание, что важно использовать close(), чтобы избежать получения ошибки "делает слишком много открытых файлов", если у вас есть несколько результатов (спасибо mateuscb за указание на это в комментариях).


Используя system(), вывод команды печатается автоматически, а значение, которое вы можете поймать, это код возврата:

$ awk 'BEGIN {d=system("date"); print "returns", d}'
Thu Jul 28 10:16:12 CEST 2016
returns 0
$ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}'
ls: cannot access asdfasdfasd: No such file or directory
returns 2
27 голосов
/ 25 декабря 2009

разобрался.

Мы используем awk's Двусторонний ввод / вывод

{
  "strip $1" |& getline $1
}

передает $ 1 в полосу, а getline возвращает вывод из полосы обратно в $ 1

6 голосов
/ 07 июня 2013
gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}'
3 голосов
/ 01 мая 2018

Вы можете использовать это, когда вам нужно обработать вывод grep:

echo "some/path/exex.c:some text" | awk -F: '{ "basename "$1"" |& getline $1; print $1 " ==> " $2}'

опция -F: указать awk на использование : в качестве разделителя полей

"basename "$1"" выполнить команду оболочки basename в первом поле

|& getline $1 читает вывод предыдущей команды оболочки в подпотоке

output:
exex.c ==> some text
...