Перенаправить в файл STDOUT первый и затем STDERR - PullRequest
0 голосов
/ 01 июня 2019

У меня есть такой код gwak.

#!/usr/bin/gawk -f

1 {
    for (i=0;i<5;i++){
        print $0
        print $0, i > "/dev/stderr"
    }
}

Я хочу перенаправить в файл tmp, сначала stdout, а затем stderr. Я попробовал это gawk -f Documents/gawk_script.awk ./file &> tmp.

Но этот вызов добавляет к файлу первый stderr. Я не хочу делить их на два файла, поэтому я спрашиваю, есть ли способ сделать это.

В ./file есть такая строка

hello
hello
howareyou
well
well

в то время как в файле tmp

hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
howareyou
howareyou
howareyou
howareyou
howareyou
well
well
well
well
well
well
well
well
well
well
well
hello 0
hello 1
hello 2
hello 3
hello 4 
hello 0
hello 1
hello 2
hello 3
hello 4
howareyou 0
howareyou 1
howareyou 2
howareyou 3
howareyou 4
well 0
well 1
well 2
well 3
well 4
well 0
well 1
well 2
well 3
well 4

Ответы [ 3 ]

1 голос
/ 01 июня 2019

Нет хорошего способа * сообщить awk или оболочке, что он должен буферизовать stderr, пока инструмент не завершит работу.Будьте проще и просто сделайте следующее:

awk -f script.awk file > out 2>tmp; cat tmp >> out && rm -f tmp

В противном случае вы можете буферизовать stderr самостоятельно и печатать в конце (но это будет работать только для сообщений stderr, которые вы печатаете вручную, а не для сообщений, которые генерирует сам gawk):

{
    for (i=0;i<5;i++){
        print $0
        errs = errs $0 OFS i ORS
    }
}
END {
    printf "%s", errs > "/dev/stderr"
}

и затем вызовите как:

awk -f script.awk file > out 2>&1

Конечно, вам вообще не нужно использовать stderr, если это все, что вы делаете с ним, просто напечатайте в stdout.

* Там может быть какое-то тайное заклинание, которое вы можете использовать, чтобы это произошло, если планеты выравниваются определенным образом и / или у вас есть определенные инструменты или определенная оболочка, но просто придерживайтесь простого, как показано выше.

1 голос
/ 03 июня 2019

Проблема, с которой вы сталкиваетесь, связана с буферизацией потоков stdout и stderr.Оба потока имеют разные настройки буфера по умолчанию.Хотя stdout буферизуется при записи в терминал, он очень хорошо буферизируется при записи в поток / канал / файл.Поток stderr, с другой стороны, всегда небуферизован.Вот почему вы сначала сталкиваетесь с выводом stderr и только позже с выводом stdout в вашем файле tmp.Имейте в виду, однако, что выходные данные будут чередоваться, когда вы выводите больше строк, так как внезапно буфер stdout будет заполнен и записан в файл, затем снова с некоторым выводом stderr до следующего буфераstdout заполнен.Проблема хорошо объясняется на следующей странице:

Одним из уродливых хаков, которые вы можете применить, является использование stdbuf для изменения буферизациипотоков данных awk:

$ stdbuf -oL -eL awk '{...}' file.txt &> tmp.txt

Здесь мы используем stdbuf, чтобы установить режим буферизации потоков stdout и stderr для буферизации строки и, таким образом, будет выглядеть вывод вашего коданапример:

hello
hello 1
hello
hello 2
...

Если вы действительно хотите сначала все выходные данные stdout, а затем все stderr, вы должны следовать подходу, упомянутому Ed Morton .

1 голос
/ 01 июня 2019

Это небольшой пример:

Я не уверен, что вы имеете в виду, если я понимаю это ...

Если вы хотите перенаправить stdoutна file_out, перенаправить stderr на file_err, вы можете сделать это ...

command > file_out 2> file_err
...