2013-08-08 7 views
18

headユーティリティを入手して、標準入力の最後の行以外のすべてを表示しようとしました。私が必要とした実際のコードは、cat myfile.txt | head -n $(($(wc -l)-1))の行に沿ったものです。しかし、それはうまくいかなかった。私はダーウィン/ OS Xにこれをやっています。これは、同じ出力を得たhead -n -1という素晴らしいセマンティクスを持っていません。ファイルの最後の行以外のすべてを表示するには、コマンド置換と標準I/Oリダイレクト

これらの変形のいずれも機能しません。

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プログラムは、サブシェル/コマンド置換、遠方の可能性に物を渡す前に標準入力を消費していないが、とにかくそれを排除したいと思っていると私に言います。ここでサブシェルを通じてheadwcの行動とそれらの相互作用を説明して何

echo "hello" | head -n $(cat && echo 1) 

?ご協力いただきありがとうございます。

答えて

25

headは間違ったツールです。あなたはすべてが、最後の行を見たい場合は、使用:

# Sample of incorrect code: 
echo "hello" | head -n $(wc -l | sed -E -e 's/\s//g') 

が失敗したことを

sed \$d 

理由はwcは、入力のすべてを消費し、参照するにはheadための左何もないということです。 wcは、その実行中のサブシェルからその標準入力を継承します。これはechoの出力から読み取ります。入力を消費すると、それは返され、headはデータを読み込もうとしますが、それはすべて消えてしまいます。入力を2度読みたい場合は、データをどこかに保存する必要があります。

+0

ありがとう@ウィリアム。私は 'sed'を使うことができましたが、この質問では' head 'を使ったアプローチがなぜうまくいかないのかを具体的に理解しようとしています。 – gkb0986

+0

+1なぜ地球上でこれが落とされたのですか? 'sed'スクリプトは、正しい、移植可能な解決策であり、説明に欠陥がないことがわかります。 – tripleee

+0

downvoteは合理的でした。それは、答えがまったく問題にならなかった「sed」解決策だけであるときに発生しました。 –

40

head -n -1は、入力の最後の行を除くすべてのものを提供します。

+4

あなたがその構文をサポート 'head'を使用することが起こる場合。すべてではありません。 –

+0

ありがとう@ dunc123。しかし、私は 'head -n -1'のサポートがないという明確化を加えました。 – gkb0986

+0

かなり驚くべきもの。共有してくれてありがとう。 – TechJS

6

は、sedを使用して:

sed '$d' filename 

は、ファイルの最後の行を削除します。この仕事のために

$ seq 1 10 | sed '$d' 
1 
2 
3 
4 
5 
6 
7 
8 
9 
+0

この 'sed'メソッドは、示されている' head'ソリューションとの違いで、FreeBSDで動作します。 –

0
awk 'NR>1{print p}{p=$0}' 

、awkはワンライナーは、sedのものよりも少し長いです。

4
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が開始されるまでにパイプに読み込まれるデータはありません。

入力がファイルからのものである場合は、wcheadの両方をそのファイルからリダイレクトできます。

head -n $(($(wc -l <myfile.txt) - 1)) <myfile.txt 

パイプからデータが得られる場合は、データを複製する必要があります。 teeからの2つの出力が同じ速度で製造されているので、headを開始する前に、完全にその出力を消費する必要がwcここのに対し、ストリームを複製する通常のツールがteeですが、それはここでは十分ではありません。その代わりに、最後の行を検出できる単一のツールを使用する必要があります。これはとにかく効率的なアプローチです。 sedの便利な

は、最後の行を一致させる方法を提供しています。どちらのすべての行を印刷しますが、最後、または最後の出力行を抑制し、動作します:MacのOS Xの場合

sed -n '$! p' 
sed '$ d' 
+0

+1の代替案の非常に有用な説明です。 – gkb0986

4

は、具体的には、私はcomment to this Q&Aから答えを見つけました。

gheadのコマンドを使用し、その後brew install coreutilsを実行し、あなたが自作を使用していると仮定すると:あなたはせずにコマンドを使用したい場合はbrew info coreutilsを参照してください、

ghead -n -1 myfile.txt 

最後に:

cat myfile.txt | ghead -n -1 

または、同等のg接頭辞(例えば、head代わりのghead)。

関連する問題