ログファイルがあり、404dのGETリクエストからURLを抽出する必要があります。
私は以下を使用しました:
grep 404 testfile.txt | cut -f 2 -d '"' | cut -f 2 -d '/' | cut -f 1 -d ' ' | sort -u
このようにカットコマンドを一緒に入れることはお勧めできません。一行で合わせることができますか?たとえば、3番目の「/」と6番目の「」から切り抜き始めます。
ログファイルの例:
ip - - [12/Dec/2019:13:18:00 +0000] "GET /test.html HTTP/1.1" 200 710 "-" "python-requests/2.18.4"
ip - - [12/Dec/2019:13:18:00 +0000] "GET /403dz2.html HTTP/1.1" 404 492 "-" "python-requests/2.18.4"
結果:
403dz2.html,
is0pmq.html,
iw30ce.html,
nbk0px.html,
答え1
以前のようにコマンドを一緒にパイピングすることには問題はありません。cut
ただし、大きな入力に対してこれを行うより効率的な方法がある可能性があることに注意してください。これは、あなたの例では、入力ファイルが端末に出力される前にコマンドとして5回処理される必要があるためです(grep
フィルタリングのために1回、別々のcut
解析コマンド3つ、解析のために1回sort
)。パイプを少なく使用可能パフォーマンスは向上しますが、これは最終的にコマンド自体と実行する操作によって異なります(つまり、3つの高速で簡単な作業が1つの大規模で計算集約的な作業よりも高速です)。入力データが比較的小さい場合は、パイプライン方式を使用するか、次のいずれかの方法を使用するかどうかに違いはありません。
メモ:次の例は、OPの元のコマンドチェーンと比較してどれだけ効率的か高速なのかわかりません。ユースケースに応じて、いくつかは他のものよりも「良い」かもしれません。
使用awk
: (尊重)
awk '$9=="404" {print substr($7,2)","}' testfile.txt
上記はRomeoの答えと似ていますが、ログ出力のファイル名から先行スラッシュを削除し、目的の結果に一致するようにコンマを末尾に追加します。awk
入力データを1行ずつ(デフォルトで)解析し、各行をスペース区切り(デフォルト)に分割するコマンド。このコマンドは9番目のフィールド(HTTPレスポンスコード)をチェックし、404
一致する場合は7番目のフィールドの部分文字列を2番目の文字から最後()まで取得し、substr($7,2)
そのフィールドの後にコンマ()を追加して出力を印刷します。","
以下についてもっと読むことができます。awk
ここ。
cut
1+ で例を使用すると、次のようにsed
なります。
grep '" 404' testfile.txt | cut -d' ' -f7 | sed 's/\///; s/$/,/'
ファイル名を抽出するには、3 つの個別の切り取りコマンドは必要なく、スペース区切り文字を使用する場合は 1 つだけが必要です。このcut
コマンドはロープを引き出します/403dz2.html
。これにより、sed
前のスラッシュ(s/\///
)が削除され、s/$/,/
最後にコンマ()が追加されます。何sed
ですか実際にここで実行される操作は代替です。文字列は、s/replace this/with this/
最初のsed
文字列()が2番目の文字列replace this
(with this
)に置き換えられることを示します。最初の置換コマンドは何もsed
変更しないように指示し/
、2番目のコマンドは$
行末()をに "置き換えます" ,
。以下についてもっと読むことができます。sed
ここ。また、私がgrep
これを行っていることに注意してください" 404
。これは少しハッキーですが、他のgrep
場所に表示される行(ファイル名、ファイルサイズ、日付など)については404を返しません。
使用perl
:
grep '" 404' testfile.txt | perl -lane 'print substr($F[6],1).","'
これは例と似ていますが、入力をフィルタリングするawk
ためにも使用されます。grep
同じアイデアを使用して、awk
7番目substr($F[6],1)
のフィールド()の部分文字列を印刷し、.","
出力にコンマ()を追加します。 Perlは0から計算を開始し、awkは1から計算を開始するため、awkでasを使用してinを使用して7番目のフィールドを$F[6]
取得します。指示を見つけることができますperl
$7
perl
ここ。
答え2
区切り文字スペース( )を使用してフィルタリングしてみましたか?
awk '$9=="404" {print $7}' testfile.txt|sort -u
または以下を使用してください。
grep 404 testfile.txt | cut -f 7 -d ' '|sort -u
PSたとえば、ダウンロードの長さが404バイトの場合、2番目の方法が一致します。または、年に404文字列が含まれています。または、要求されたURLにこの文字列が含まれています。
答え3
使用awk
コマンド:
awk -F '[ /]' '/ 404 / {print $10|"sort -u"}' testfile.txt
説明する:
-F '[ /]'
:スペース ""とスラッシュ "/"を区切り文字として使用します。 (複数の区切り記号)/ 404 /
:「404」を含む行だけが一致します。grep " 404 " testfile.txt
仕事と同じです。
ノート:「404」の前後に多少のスペースがあります。
これにより、レスポンスコードではなくURLに表示される可能性がある誤った肯定一致が削除されます。たとえば、次の行は一致しません。
ip - - [12/Dec/2019:13:18:00 +0000] "GET /test404.html HTTP/1.1" 200 710 "-" "python-requests/2.18.4"
ノート:test404.htmlURLに次のものが含まれています404しかし、レスポンスコードは200。したがって、「404」の前後にスペースが必要です。
print $10
:10番目のフィールドを表示するには、スペースとスラッシュを区切り文字として使用します。| sort -u
: 結果をソートし、重複インスタンスを 1 つだけ取得します。 (つまり、行のみを表示)testfile.txt
:一致させる行を含むファイル。
ノート: 別の行があるが404
興味がないと仮定すると、次のように一致を絞り込むことができます。
awk -F '[ /]' '/GET.* 404 / {print $10|"sort -u"}' testfile.txt
修正内容:
/GET.* 404 /
GET
:「次に他のものが続き、次に」が含まれている404
行のみが一致します。
ついに:
URLの前にスラッシュを追加するには、次のようにします。
awk '/ 404 / {print $7|"sort -u"}' testfile.txt
URLの後にカンマを追加するには、次のようにします。
awk -F '[ /]' '/ 404 / {print $10","|"sort -u"}' testfile.txt
URLの前にスラッシュを追加し、URLの後にコンマを追加するには、次のようにします。
awk '/ 404 / {print $7","|"sort -u"}' testfile.txt