Txtファイルがあるとします。ファイルの上位10行と下位10行を同時に表示するコマンドは何ですか?
つまり、ファイルの長さが200行の場合、1行目から10行目および190行目から200行目を一度に表示します。
簡単にできます:
(head; tail) < file.txt
何らかの理由でパイプを使用する必要がある場合は、次のようにします。
cat file.txt | (head; tail)
注:file.txtの行数がデフォルトのヘッドの行+デフォルトのテールの行より少ない場合、重複した行を印刷します。
ed
はstandard text editor
です
$ echo -e '1+10,$-10d\n%p' | ed -s file.txt
純粋なストリーム(コマンドからの出力など)の場合、「tee」を使用してストリームを分岐し、1つのストリームを先頭に、1つのストリームを末尾に送信できます。これには、bashの「>(list)」機能(+/dev/fd/N)を使用する必要があります。
( COMMAND | tee /dev/fd/3 | head ) 3> >( tail )
または/ dev/fd/N(または/ dev/stderr)に加えて、複雑なリダイレクトを行うサブシェルを使用します。
( ( seq 1 100 | tee /dev/fd/2 | head 1>&3 ) 2>&1 | tail ) 3>&1
( ( seq 1 100 | tee /dev/stderr | head 1>&3 ) 2>&1 | tail ) 3>&1
(これらはどちらもcshまたはtcshでは機能しません。)
少しうまく制御できるものについては、次のPerlコマンドを使用できます。
COMMAND | Perl -e 'my $size = 10; my @buf = (); while (<>) { print if $. <= $size; Push(@buf, $_); if ( @buf > $size ) { shift(@buf); } } print "------\n"; print @buf;'
(sed -u 10q; echo ...; tail) < file.txt
(head;tail)
テーマのもう1つのバリエーションですが、小さなファイルの初期のバッファーフィルの問題を回避します。
head -10 file.txt; tail -10 file.txt
それ以外は、独自のプログラム/スクリプトを作成する必要があります。
すべてのユースケースをカバーしている唯一のソリューションであると思われるこのソリューションに至るまで、多くの時間がかかりました(これまで):
command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
'{
if (NR <= offset) print;
else {
a[NR] = $0;
delete a[NR-offset];
printf "." > "/dev/stderr"
}
}
END {
print "" > "/dev/stderr";
for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
{ print a[i]}
}'
機能リスト:
J.F。Sebastianのコメント に基づく:
cat file | { tee >(head >&3; cat >/dev/null) | tail; } 3>&1
この方法では、最初の行と残りの行を1つのパイプで異なる方法で処理できます。これは、CSVデータを操作するのに役立ちます。
{ echo N; seq 3;} | { tee >(head -n1 | sed 's/$/*2/' >&3; cat >/dev/null) | tail -n+2 | awk '{print $1*2}'; } 3>&1
N * 2 2 4 6
ここでの問題は、ストリーム指向のプログラムが事前にファイルの長さを知らないことです(実際のストリームの場合、ファイルがない可能性があるため)。
tail
などのツールは、表示された最後のn行をバッファリングし、ストリームの終わりを待ってから印刷します。
単一のコマンドでこれを実行したい場合(およびオフセットで動作させ、重複する行を繰り返さないようにする場合)、この動作をエミュレートする必要があります。
このawkを試してください:
awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile
File.extの最初の10行、最後の10行:
cat file.ext | head -10 && cat file.ext | tail -10
ファイルの最後の10行、次に最初の10行:
cat file.ext | tail -10 && cat file.ext | head -10
その後、他の場所でも出力をパイプできます。
(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program
これを行う簡単なpythonアプリを作成しました: https://Gist.github.com/garyvdm/9970522
パイプ(ストリーム)とファイルを処理します。
まあ、いつでも一緒に連鎖させることができます。そのように、head fiename_foo && tail filename_foo
。これで十分でない場合は、.profileファイルまたは使用するログインファイルにbash関数を記述できます。
head_and_tail() {
head $1 && tail $1
}
そして、後でシェルプロンプトから呼び出します:head_and_tail filename_foo
。
上記のアイデアを活用(テスト済みbashおよびzsh)
しかし、エイリアス「帽子」を使用して頭と尾
alias hat='(head -5 && echo "^^^------vvv" && tail -5) < '
hat large.sql
パイプ(ストリーム)とファイルを処理するには、これを.bashrcまたは.profileファイルに追加します。
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' ; }
その後、あなたはできません
headtail 10 < file.txt
だけでなく
a.out | headtail 10
(これは、単純な古いa.out | (head; tail)
とは異なり、10が入力の長さを超えたときに、まだ空白の空白行を追加します。以前の回答者に感謝します。)
注:headtail 10
ではなく、headtail -10
。
ファイルのサイズによっては、その内容を積極的に読み取ることは望ましくない場合があります。その状況では、いくつかの単純なシェルスクリプトで十分だと思います。
分析していた非常に大きなCSVファイルでこれを最近処理した方法は次のとおりです。
$ for file in *.csv; do echo "### ${file}" && head ${file} && echo ... && tail ${file} && echo; done
これにより、各ファイルの最初の10行と最後の10行が出力されます。また、ファイル名と省略記号が前後に出力されます。
単一の大きなファイルの場合、同じ効果を得るために単純に次を実行できます。
$ head somefile.csv && echo ... && tail somefile.csv
sed -n "1,10p; $(( $(wc -l ${aFile} | grep -oE "^[[:digit:]]+")-9 )),\$p" "${aFile}"
NOTE:aFile変数には、ファイルのフルパスが含まれます。
@Samus_の説明に基づいて構築します here @Aleksandra Zalcmanのコマンドの動作方法について、このバリエーションは、行を数えずにテールの開始位置をすばやく見つけることができない場合に便利です。
{ head; echo "####################\n...\n####################"; tail; } < file.txt
または、20行以外で作業を開始する場合、行数が役立つこともあります。
{ head -n 18; tail -n 14; } < file.txt | cat -n
ファイルの最初の10行と最後の10行を印刷するには、これを試すことができます。
cat <(head -n10 file.txt) <(tail -n10 file.txt) | less
私はしばらくの間、このソリューションを探していました。 sedで自分で試してみましたが、ファイル/ストリームの長さが事前にわからないという問題は乗り越えられません。上記で利用可能なすべてのオプションの中で、私はCamille Goudeseuneのawkソリューションが気に入っています。彼は、彼のソリューションが十分に小さなデータセットで出力に余分な空白行を残したことをメモしました。ここで、余分な行を削除する彼のソリューションの修正を提供します。
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { a_count=0; for (i in a) {a_count++}; for (i=NR-a_count+1; i<=NR; i++) print a[i] }' ; }
このタスクにsed
を使用しないのはなぜですか?
sed -n -e 1,+9p -e 190,+9p textfile.txt