head
ユーティリティを取得して、標準入力の最後の行を除くすべてを表示しようとしています。実際に必要なコードは、cat myfile.txt | head -n $(($(wc -l)-1))
の行に沿ったものです。しかし、それはうまくいきませんでした。私はこれをhead -n -1
のニースセマンティクスを持たないDarwin/OS Xで行っています。
これらのバリエーションはいずれも機能しません。
cat myfile.txt | head -n $(wc -l | sed -E -e 's/\s//g')
echo "hello" | head -n $(wc -l | sed -E -e 's/\s//g')
より多くのバリエーションをテストし、特にこれが機能することがわかりました。
cat <<EOF | echo $(($(wc -l)-1))
>Hola
>Raul
>Como Esta
>Bueno?
>EOF
3
ここでも動作する簡単なものがあります。
echo "hello world" | echo $(($(wc -w)+10))
これは当然、違法な行数エラーを私に与えます。しかし、少なくとも、head
プログラムは、サブシェル/コマンド置換にリモートで渡す前に標準入力を消費しないことを教えてくれますが、とにかく除外したいものです。
echo "hello" | head -n $(cat && echo 1)
ここでhead
とwc
の動作とサブシェルを介したそれらの相互作用を説明していますか?ご協力いただきありがとうございます。
head
は間違ったツールです。最後の行以外をすべて表示する場合は、次を使用します。
sed \$d
その理由
# Sample of incorrect code:
echo "hello" | head -n $(wc -l | sed -E -e 's/\s//g')
失敗するのは、wc
がすべての入力を消費し、head
が表示するものが何もないことです。 wc
は、実行しているサブシェルから標準入力を継承します。サブシェルは、echo
の出力から読み取ります。入力を消費すると、戻り、head
がデータの読み取りを試みますが、すべて消えてしまいます。入力を2回読み取る場合は、データをどこかに保存する必要があります。
head -n -1
は、入力の最終行を除くすべてを提供します。
Sedの使用:
sed '$d' filename
ファイルの最後の行を削除します。
$ seq 1 10 | sed '$d'
1
2
3
4
5
6
7
8
9
特にMac OS Xについては、 このQ&Aへのコメント からの回答を見つけました。
Homebrewを使用している場合、brew install coreutils
その後、ghead
コマンドを使用します。
cat myfile.txt | ghead -n -1
または、同等に:
ghead -n -1 myfile.txt
最後に、brew info coreutils
接頭辞g
なしでコマンドを使用する場合(例:head
の代わりにghead
)。
_cat myfile.txt | echo $(($(wc -l)-1))
_
これは動作します。それは非常に複雑です:echo $(($(wc -l)-1)) <myfile.txt
またはecho $(($(wc -l <myfile.txt)-1))
と書くことができます。問題はあなたがそれを使用している方法です。
_cat myfile.txt | head -n $(wc -l | sed -E -e 's/\s//g')
_
wc
は、行をカウントしているため、すべての入力を消費します。そのため、head
が開始されるまでに、パイプに読み取るデータは残っていません。
入力がファイルからのものである場合、そのファイルからwc
とhead
の両方をリダイレクトできます。
_head -n $(($(wc -l <myfile.txt) - 1)) <myfile.txt
_
データがパイプから取得される可能性がある場合は、それを複製する必要があります。ストリームを複製する通常のツールはtee
ですが、tee
からの2つの出力は同じレートで生成されるため、ここでは十分ではありませんが、ここではwc
は完全に消費する必要がありますhead
を開始する前の出力。したがって、代わりに、最後の行を検出できる単一のツールを使用する必要があります。これは、いずれにしても効率的なアプローチです。
便利なことに、sedは最後の行を一致させる方法を提供します。最後の行を除くすべての行を印刷するか、最後の出力行を抑制します:
_sed -n '$! p'
sed '$ d'
_
awk 'NR>1{print p}{p=$0}'
このジョブでは、awkワンライナーはsedワンライナーよりも少し長くなります。