最短ファイルで「貼り付け」コマンドを停止する方法

最短ファイルで「貼り付け」コマンドを停止する方法

2つのファイルがあります。

a.txt

1
2
3

b.txt

foo
bar
baz
qux

paste a.txt b.txt走る

1 foo 
2 bar 
3 baz 
 qux 

しかし、最も短いファイルの終わりに停止したいと思います。つまり、行全体を印刷したいだけです。それ以外の場合、パイプラインの後続のプログラムは、最初のフィールドquxが2番目のフィールドであると考えます。方法)。どうすればいいですか?

答え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か?

プロセス置換を含む<(…)シェルが必要です(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(つまり、bashismなし)。

paste a.txt b.txt | head -n $( { wc -l <a.txt; wc -l b.txt; } | sort -n | head -n 1 )

paste出力をにパイプするので、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多くの計算努力が無駄にならないことを意味します。

関連情報