web-dev-qa-db-ja.com

unix-ファイルの先頭と末尾

Txtファイルがあるとします。ファイルの上位10行と下位10行を同時に表示するコマンドは何ですか?

つまり、ファイルの長さが200行の場合、1行目から10行目および190行目から200行目を一度に表示します。

117
toop

簡単にできます:

(head; tail) < file.txt

何らかの理由でパイプを使用する必要がある場合は、次のようにします。

cat file.txt | (head; tail)

注:file.txtの行数がデフォルトのヘッドの行+デフォルトのテールの行より少ない場合、重複した行を印刷します。

184

edstandard text editorです

$ echo -e '1+10,$-10d\n%p' | ed -s file.txt
18
kev

純粋なストリーム(コマンドからの出力など)の場合、「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;'
11
RantingNerd
(sed -u 10q; echo ...; tail) < file.txt

(head;tail)テーマのもう1つのバリエーションですが、小さなファイルの初期のバッファーフィルの問題を回避します。

5
guest

head -10 file.txt; tail -10 file.txt

それ以外は、独自のプログラム/スクリプトを作成する必要があります。

3
mah

すべてのユースケースをカバーしている唯一のソリューションであると思われるこのソリューションに至るまで、多くの時間がかかりました(これまで):

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]}
           }'

機能リスト:

  • ヘッドのライブ出力(明らかにテールの出力は不可能です)
  • 外部ファイルを使用しない
  • プログレスバーMAX_LINESの後の各行に1つのドット。長時間実行されるタスクに非常に便利です。
  • stderrのプログレスバー、進行状況ドットがヘッド+テールから分離されていることを保証します(stdoutをパイプする場合に非常に便利です)
  • バッファリング(stdbuf)による不正なログ順序の可能性を回避
  • 行の総数がhead + tailより小さい場合、出力の重複を避けます。
3
sorin

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 
2
modular

ここでの問題は、ストリーム指向のプログラムが事前にファイルの長さを知らないことです(実際のストリームの場合、ファイルがない可能性があるため)。

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
2
Samus_

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

1
Paul

これを行う簡単なpythonアプリを作成しました: https://Gist.github.com/garyvdm/9970522

パイプ(ストリーム)とファイルを処理します。

1

まあ、いつでも一緒に連鎖させることができます。そのように、head fiename_foo && tail filename_foo。これで十分でない場合は、.profileファイルまたは使用するログインファイルにbash関数を記述できます。

head_and_tail() {
    head $1 && tail $1
}

そして、後でシェルプロンプトから呼び出します:head_and_tail filename_foo

1
S.R.I

上記のアイデアを活用(テスト済みbashおよびzsh)

しかし、エイリアス「帽子」を使用して頭と尾

alias hat='(head -5 && echo "^^^------vvv" && tail -5) < '


hat large.sql
1
zzapper

パイプ(ストリーム)とファイルを処理するには、これを.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

0

ファイルのサイズによっては、その内容を積極的に読み取ることは望ましくない場合があります。その状況では、いくつかの単純なシェルスクリプトで十分だと思います。

分析していた非常に大きなCSVファイルでこれを最近処理した方法は次のとおりです。

$ for file in *.csv; do echo "### ${file}" && head ${file} && echo ... && tail ${file} && echo; done

これにより、各ファイルの最初の10行と最後の10行が出力されます。また、ファイル名と省略記号が前後に出力されます。

単一の大きなファイルの場合、同じ効果を得るために単純に次を実行できます。

$ head somefile.csv && echo ... && tail somefile.csv
0
Jitsusama
sed -n "1,10p; $(( $(wc -l ${aFile} | grep -oE "^[[:digit:]]+")-9 )),\$p" "${aFile}"

NOTEaFile変数には、ファイルのフルパスが含まれます。

0
mark_infinite

@Samus_の説明に基づいて構築します here @Aleksandra Zalcmanのコマンドの動作方法について、このバリエーションは、行を数えずにテールの開始位置をすばやく見つけることができない場合に便利です。

{ head; echo "####################\n...\n####################"; tail; } < file.txt

または、20行以外で作業を開始する場合、行数が役立つこともあります。

{ head -n 18; tail -n 14; } < file.txt | cat -n
0
Script Wolf

ファイルの最初の10行と最後の10行を印刷するには、これを試すことができます。

cat <(head -n10 file.txt) <(tail -n10 file.txt) | less

0
mariana.ft

私はしばらくの間、このソリューションを探していました。 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] }' ; }
0
Michael Blahay

このタスクにsedを使用しないのはなぜですか?

sed -n -e 1,+9p -e 190,+9p textfile.txt

0
lik