web-dev-qa-db-ja.com

Linuxでテキストファイルから特定の行を表示する方法

Linuxの便利なcmd行ユーティリティheadtailは誰もが知っていると思います。 headを使用すると、ファイルの最初のX行を印刷できます。tailも同じことを行いますが、ファイルの最後を印刷します。ファイルの途中を印刷するのに適したコマンドは何ですか?何かのようなもの middle --start 10000000 --count 20(10000'000番目から10000'010番目の行までを印刷します)。

大きなファイルを効率的に処理できるものを探しています。私は試した tail -n 10000000 | head 10そしてそれは恐ろしく遅いです。

92
Boaz
sed -n '10000000,10000020p' filename

あなたはこれを少しこのようにスピードアップできるかもしれません:

sed -n '10000000,10000020p; 10000021q' filename

これらのコマンドでは、オプション-nにより、sedが「パターンスペースの自動印刷を抑制」します。 pコマンド「現在のパターンスペースを印刷[s]」およびqコマンド「これ以上入力を処理せずにsedスクリプトをすぐに終了[s] ...」引用符は sedman page

ちなみに、あなたのコマンド

tail -n 10000000 filename | head 10

ファイルのendから1000万行目から始まりますが、「middle」コマンドはbeginningこれは以下と同等です。

head -n 10000010 filename | tail 10

問題は、可変長行を含むソートされていないファイルの場合、プロセスは改行をカウントしてファイルを通過する必要があることです。それをショートカットする方法はありません。

ただし、ファイルがソートされている場合(タイムスタンプが含まれているログファイルなど)、または固定長の行がある場合は、バイト位置に基づいてファイルをシークできます。ログファイルの例では、my Python script here *の場合と同様に、ある範囲のバイナリ検索を実行できます。固定レコード長のファイルの場合、それは本当に簡単です。ファイルにlinelength * linecount文字をシークするだけです。

*そのスクリプトにさらに別の更新を投稿するつもりです。たぶん、いつの日かそれを回避するでしょう。

sedの次の使用法を見つけました

sed -n '10000000,+20p'  filename

それが誰かに役立つことを願っています!

29
Dox

初めての投稿です!とにかく、これは簡単です。 file.txtというファイルから8872行目を取得するとします。方法は次のとおりです。

cat -n file.txt | grep '^ * 8872'

ここで問題は、この後20行を見つけることです。これを達成するには

cat -n file.txt | grep -A 20 '^ * 8872'

前後の行については、grepマニュアルの-Bおよび-Cフラグを参照してください。

4
Dennis

次のコマンドを使用して、特定の範囲の行を取得します。

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

ここで、debug.logは、欠落した行で構成されるファイルであり、1220974行番号から1513793までの行をファイルtest.logに出力するために使用しました。ラインの範囲をキャプチャするのに役立つことを願っています。

1
newbie13

デニスのsedの答えは行く方法です。しかし、頭と尾だけを使用して、bashの下で:

中央(){頭-n $ [$ 1 + $ 2] |尾-n $ 2; } 

これは最初の$ 1 + $ 2行を2回スキャンするため、Dennisの回答よりもはるかに悪いです。しかし、それを使用するためにこれらすべてのsed文字を覚えておく必要はありません。

1
Charles Stewart

A Rubyワンライナーバージョン。

Ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

それは誰かに役立つことができます。 DennisとDoxが提供する「sed」を使用したソリューションは非常に高速です。

0
shardan

Perlが王様です:

Perl -ne 'print if ($. == 10000000 .. $. == 10000020)' filename
0
Peter V. Mørch

行番号がわかっている場合は、ファイルから1行目、3行目、5行目を取得する場合は、/ etc/passwdと指定します。

Perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
0
Dagelf

「nl」を使用できます。

nl filename | grep <line_num>
0
Ajay

たとえば、このawkは20〜40の行を印刷します

awk '{if((NR> 20)&&(NR <40))print $ 0}'/etc/passwd

0
Hrvoje Špoljar