先重定向到文件 STDOUT,然后再重定向到 STDERR
Redirect to a file STDOUT first and then STDERR
我有这样的 gawk 代码。
#!/usr/bin/gawk -f
1 {
for (i=0;i<5;i++){
print [=10=]
print [=10=], 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
这是一个小例子:
我不太明白你的意思,如果我明白了...
如果你想将 stdout
重定向到 file_out
,将 stderr
重定向到 file_err
,你可以这样做...
command > file_out 2> file_err
没有好的方法*告诉 awk 或 shell 它必须缓冲 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 [=11=]
errs = errs [=11=] OFS i ORS
}
}
END {
printf "%s", errs > "/dev/stderr"
}
然后调用为:
awk -f script.awk file > out 2>&1
当然,如果您只使用它,您实际上根本不需要使用 stderr,只需打印到 stdout。
*如果行星以某种方式对齐,您可能会使用一些神秘的咒语来实现这一点 and/or 您有某些工具或某种 shell 但请保持简单,如图所示以上。
您遇到的问题是由于流 stdout
和 stderr
的缓冲造成的。两个流都有不同的默认值 buffer-settings。虽然 stdout
在写入终端时是 line-buffered,但在写入 stream/pipe/file 时缓冲得很好。另一方面,流 stderr
总是 无缓冲。这就是为什么您首先遇到 stderr
的输出,然后才在文件 tmp
中遇到 stdout
的输出。但是请注意,当您输出更多行时,输出将交错,因为突然之间 stdout
的缓冲区将满并写入文件,然后再次输出 stderr
直到stdout
的下一个缓冲区已满。下一页很好地解释了这个问题:
您可以应用的丑陋技巧之一是使用 stdbuf
来更改 awk
:
的数据流缓冲
$ stdbuf -oL -eL awk '{...}' file.txt &> tmp.txt
此处我们使用 stdbuf
将流 stdout
和 stderr
的缓冲模式设置为 line-buffering,因此您的代码输出如下所示:
hello
hello 1
hello
hello 2
...
如果你真的想要先 all 输出 stdout
然后是 stderr
的所有输出,你应该遵循 [=30= 提到的方法].
有点旧,但如果有人还需要它:
echo "some stuff" | awk '{
for (i=0;i<5;i++){
print [=10=];
# print i on stderr
system(">&2 echo " i);
}
}'
我有这样的 gawk 代码。
#!/usr/bin/gawk -f
1 {
for (i=0;i<5;i++){
print [=10=]
print [=10=], 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
这是一个小例子:
我不太明白你的意思,如果我明白了...
如果你想将 stdout
重定向到 file_out
,将 stderr
重定向到 file_err
,你可以这样做...
command > file_out 2> file_err
没有好的方法*告诉 awk 或 shell 它必须缓冲 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 [=11=]
errs = errs [=11=] OFS i ORS
}
}
END {
printf "%s", errs > "/dev/stderr"
}
然后调用为:
awk -f script.awk file > out 2>&1
当然,如果您只使用它,您实际上根本不需要使用 stderr,只需打印到 stdout。
*如果行星以某种方式对齐,您可能会使用一些神秘的咒语来实现这一点 and/or 您有某些工具或某种 shell 但请保持简单,如图所示以上。
您遇到的问题是由于流 stdout
和 stderr
的缓冲造成的。两个流都有不同的默认值 buffer-settings。虽然 stdout
在写入终端时是 line-buffered,但在写入 stream/pipe/file 时缓冲得很好。另一方面,流 stderr
总是 无缓冲。这就是为什么您首先遇到 stderr
的输出,然后才在文件 tmp
中遇到 stdout
的输出。但是请注意,当您输出更多行时,输出将交错,因为突然之间 stdout
的缓冲区将满并写入文件,然后再次输出 stderr
直到stdout
的下一个缓冲区已满。下一页很好地解释了这个问题:
您可以应用的丑陋技巧之一是使用 stdbuf
来更改 awk
:
$ stdbuf -oL -eL awk '{...}' file.txt &> tmp.txt
此处我们使用 stdbuf
将流 stdout
和 stderr
的缓冲模式设置为 line-buffering,因此您的代码输出如下所示:
hello
hello 1
hello
hello 2
...
如果你真的想要先 all 输出 stdout
然后是 stderr
的所有输出,你应该遵循 [=30= 提到的方法].
有点旧,但如果有人还需要它:
echo "some stuff" | awk '{
for (i=0;i<5;i++){
print [=10=];
# print i on stderr
system(">&2 echo " i);
}
}'