如何使“粘贴”命令停止在最短的文件上

如何使“粘贴”命令停止在最短的文件上

我有两个文件:

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处理大量数据的情况下,不会浪费太多的计算工作......

相关内容