我有两个文件:
a.txt
1
2
3
b.txt
foo
bar
baz
qux
跑步paste a.txt b.txt
给予
1 foo
2 bar
3 baz
qux
但是,我想在最短的文件结束时停止(也就是说,我只想打印完整的行,否则管道中的后续程序会认为qux
第一个字段是第二个字段,而实际上这是唯一的方法)。我怎样才能做到这一点?
答案1
与其他答案相同的想法 - 粘贴所有行,然后选择完整的行 - 但使用awk
:
paste a.txt b.txt | awk NF==2
答案2
使用sed
命令可以删除缺少起始编号的行:
paste a.txt b.txt | sed '/^\s/d'
结果:
1 foo
2 bar
3 bax
答案3
计算行数和head
文件数?
需要一个带有进程替换 ( <(…)
) 的 shell(使用 bash):
$ a=$(wc -l <a.txt)
$ b=$(wc -l <b.txt)
$ if [ "$a" -lt "$b" ]; then min=$a; else min=$b; fi
$ paste <( head '-'"$min" <a.txt ) <(head '-'"$min" <b.txt)
1 foo
2 bar
3 bax
答案4
我们可以使用这个命令,它应该在大多数 POSIX 中运行sh
(即没有 bashisms)
paste a.txt b.txt | head -n $( { wc -l <a.txt; wc -l b.txt; } | sort -n | head -n 1 )
因为它将把 的输出通过管道传输paste
到 a 中head -n <lines>
,只允许行数较少的文件通过。
这是一个评论版本:
# We let `paste` do its job normally, with output send into a pipe...
paste a.txt b.txt |
# ...to `head`, which will stop said output after `-n` lines...
head -n $(
# ...that are determined by the `wc` counted line lengths `-l` ...
{
wc -l <a.txt # ...of file a.txt...
wc -l <b.txt # ...and file b.txt ...
} |
# ... being piped to be `sort`ed numerically ascendet list...
sort -n |
# ... where the lower line count being the first line (i.e. "3)
head -n 1
)
和
cat >a.txt << 'EOF'
1
2
3
EOF
# and
cat >b.txt << 'EOF'
foo
bar
baz
qux
EOF
# running...
paste a.txt b.txt | head -n $( { wc -l <a.txt; wc -l b.txt; } | sort -n | head -n 1 )
...产生所需的输出
1 foo
2 bar
3 bax
请注意,在大多数设置中应该有一个SIGPIPE
信号发生,如上所述man pipe(7)
应该 :
如果引用管道读取端的所有文件描述符都已关闭,则 write(2) 将导致为调用进程生成 SIGPIPE 信号。
这意味着,在paste
处理大量数据的情况下,不会浪费太多的计算工作......