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
多くの計算努力が無駄にならないことを意味します。