web-dev-qa-db-ja.com

行ごとに抽出してから、別のファイルに保存する

私はgrepsedを使って運を試しましたが、どういうわけかうまくいきませんでした。

サイズが約8 GBのログファイルがあります。 15分間の不審なアクティビティを分析する必要があります。確認する必要があるログファイルの部分を見つけ、それらの行を抽出して別のファイルに保存しようとしています。通常のCentOSマシンではどうすればよいですか?

私の最後の試みはこれでしたが、うまくいきませんでした。 sedとそれらのタイプのコマンドに関しては、私は途方に暮れています。

sed -n '2762818,2853648w /var/log/output.txt' /var/log/logfile
7
koljanep
sed -n '2762818,2853648p' /var/log/logfile > /var/log/output.txt

pは印刷用です

9
thiagowfx

他の人が述べたように、これを行うための最良の方法はおそらくシェルのリダイレクトを使用することです。 sedは個人的なお気に入りですが、ファイルから非常に多くの行のみを取得するように設計されているheadよりも効率的ではありません。

このサイトには、大きなファイルの場合head -n[num] | tail -n[num]が常にsedよりもパフォーマンスが優れていることを証明する他の回答がありますが、おそらくパイプを完全に回避するよりも高速です。

私は次のようなファイルを作成しました:

echo | dd cbs=5000000 conv=block | tr \  \\n >/tmp/5mil_lines

そして私はそれを実行しました:

{ head -n "$((ignore=2762817))" >&2
  head -n "$((2853648-ignore))" 
} </tmp/5mil_lines 2>/dev/null  |
sed -n '1p;$p'                

私はsedだけを使用して、最初と最後の行だけを表示してあなたを示しました...

2762818
2853648

これは、{ ... ; }を使用してコマンドをグループ化し、... ; } <inputのようにグループの入力をリダイレクトすると、すべてのコマンドが同じ入力を共有するため機能します。ほとんどのコマンドは読み込み中にinfile全体を使い尽くすため、{ cmd1 ; cmd2; } <infileの場合、通常cmd1はinfileの先頭から末尾まで読み取り、cmd2には何も残されません。

ただし、headは、指示されているとおり、常にinfileを介してのみシークします。

{ head -n [num] >/dev/null
  head -n [num]
} <infile 

...最初のケースは[num]にシークし、その出力を/dev/nullにダンプします。2番目のケースは、最初のフィールドから離れたところから読み取りを開始します。

できるよ...

{ head -n "$((ignore=2762817))" >/dev/null
  head -n "$((2853648-ignore))" >/path/to/outfile
} <infile

この構成は、他の種類の複合コマンドでも機能します。例えば:

set "$((n=2762817))" "$((2853648-n))"
for n do head "-n$n" >&"$#"; shift
done <5mil_lines 2>/dev/null | 
sed -n '1p;$p'

...印刷する...

2762818
2853648

ただし、次のように機能する場合もあります。

d=$(((  n=$(wc -l </tmp/5mil_lines))/43 ))      &&
until   [ "$(((n-=d)>=(!(s=143-n/d))))" -eq 0 ] &&
        head "-n$d" >>"/tmp/${s#1}.split"
do      head "-n$d" > "/tmp/${s#1}.split"       || ! break
done    </tmp/5mil_lines

シェルの上では、最初に$nおよび$d変数を...に設定します。

  • $n
    • テストファイル/tmp/5mil_lineswcによって報告された行数
  • $d
    • $n/43の商。ここで、43は任意に選択された除数の一部です。

次にuntilをループし、$n$dだけ$dより小さい値にデクリメントします。その際、分割数を$sに保存し、その値をループで使用して、>という名前の/tmp/[num].split出力ファイルをインクリメントします。その結果、各反復で同じ数の\newlineで区切られたフィールドを新しい出力ファイルに読み取り、ループの途中で43回均等に分割します。それは、そのinfileを2回以上読み取る必要なく、それを管理します-最初の時間は、wcが行をカウントするためにそれを行うときであり、残りの操作では、書き込みと同じ数の行のみを読み取ります毎回出力ファイル。

それを実行した後、私は私のような結果をチェックしました...

tail -n1 /tmp/*split | grep .

出力:

==> /tmp/01.split <==
116279  
==> /tmp/02.split <==
232558  
==> /tmp/03.split <==
348837  
==> /tmp/04.split <==
465116  
==> /tmp/05.split <==
581395  
==> /tmp/06.split <==
697674  
==> /tmp/07.split <==
813953  
==> /tmp/08.split <==
930232  
==> /tmp/09.split <==
1046511 
==> /tmp/10.split <==
1162790 
==> /tmp/11.split <==
1279069 
==> /tmp/12.split <==
1395348 
==> /tmp/13.split <==
1511627 
==> /tmp/14.split <==
1627906 
==> /tmp/15.split <==
1744185 
==> /tmp/16.split <==
1860464 
==> /tmp/17.split <==
1976743 
==> /tmp/18.split <==
2093022 
==> /tmp/19.split <==
2209301 
==> /tmp/20.split <==
2325580 
==> /tmp/21.split <==
2441859 
==> /tmp/22.split <==
2558138 
==> /tmp/23.split <==
2674417 
==> /tmp/24.split <==
2790696 
==> /tmp/25.split <==
2906975 
==> /tmp/26.split <==
3023254 
==> /tmp/27.split <==
3139533 
==> /tmp/28.split <==
3255812 
==> /tmp/29.split <==
3372091 
==> /tmp/30.split <==
3488370 
==> /tmp/31.split <==
3604649 
==> /tmp/32.split <==
3720928 
==> /tmp/33.split <==
3837207 
==> /tmp/34.split <==
3953486 
==> /tmp/35.split <==
4069765 
==> /tmp/36.split <==
4186044 
==> /tmp/37.split <==
4302323 
==> /tmp/38.split <==
4418602 
==> /tmp/39.split <==
4534881 
==> /tmp/40.split <==
4651160 
==> /tmp/41.split <==
4767439 
==> /tmp/42.split <==
4883718 
==> /tmp/43.split <==
5000000 
2
mikeserv

おそらく、以下のようにheadtailコマンドの組み合わせを使用してこれを実現できます。

head -n{to_line_number} logfile | tail -n+{from_line_number} > newfile

from_line_numberおよびto_line_number必要な行番号を入力します。

テスト

cat logfile
This is first line.
second
Third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

##I use the command as below. I extract from 4th line to 10th line. 

head -n10 logfile | tail -n+4 > newfile
fourth
fifth
sixth
seventh
eighth
ninth
tenth
0
Ramesh