['a', 'b', 'c'].each do |el|
table_for ratings.list do
column el do |list|
table_for rating.list[el] do
column :rating
column :comment
end
end
end
end
工作正常
set -eu
VAR=$(zcat file.gz | head -n 12)
导致bash退出失败。 这怎么会导致管道故障?
请注意,file.gz包含数百万行(约750 MB,已压缩)。
答案 0 :(得分:16)
考虑一下。
zcat
将其输出写入head
。head
在读取12行之后退出,而不是超过12行的输入流。 当然你有一个错误:zcat
早期关闭了目标管道,并且无法成功编写输入文件的解压缩版本!它没有任何方式知道这是由于用户意图,通过错误发生的事情。
如果您使用zcat
写入磁盘并且空间不足或网络流耗尽并且连接丢失,那么以状态退出是完全正确的表示失败。这只是该规则的另一种情况。
操作系统给出zcat
的具体错误是EPIPE
,由write
系统调用在以下条件下返回:尝试写入任何进程都无法读取的管道。
在head
(此FIFO的唯一读取器)退出后,对于任何写入管道输入端而不是以返回EPIPE将是一个错误。对于zcat
静默忽略写入其输出的错误,从而能够生成不准确的输出流而没有反映此事件的退出状态,同样将成为错误。
如果您不想更改任何shell选项,顺便提一下,您可能会考虑使用进程替换的一种解决方法:
var=$(head -n 12 < <(zcat file.gz))
在这种情况下,zcat
不是管道组件,并且不会考虑其退出状态以确定成功。 (如果您想要进行独立的成功/失败判断,您可以测试$var
是否长12行。
通过使用本机gzip支持引入Python解释器,可以实现更全面的解决方案。嵌入在shell脚本中的本机Python实现(兼容Python 2和3.x)可能如下所示:
zhead_py=$(cat <<'EOF'
import sys, gzip
gzf = gzip.GzipFile(sys.argv[1], 'rb')
outFile = sys.stdout.buffer if hasattr(sys.stdout, 'buffer') else sys.stdout
numLines = 0
maxLines = int(sys.argv[2])
for line in gzf:
if numLines >= maxLines:
sys.exit(0)
outFile.write(line)
numLines += 1
EOF
)
zhead() { python -c "$zhead_py" "$@"; }
...它会让你zhead
在输入数据用尽时不会失败,但是 通过失败的退出状态以获得真正的I / O失败或其他突发事件。 (用法的格式为zhead in.gz 5
,从in.gz
读取5行。
答案 1 :(得分:0)
或者,您可以使用
zcat file.gz | awk '(NR<=12)'
价格是您需要遍历所有zcat
,没有根据您指定的行提早止损。