シェル - ログから日付と時刻を抽出する

シェル - ログから日付と時刻を抽出する

私のWebサーバーのログファイルは次のとおりです。

2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:07:49:01 +0100] "GET / HTTP/1.1" 200 58266 "-" "curl/7.61.1"
2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:08:49:01 +0100] "GET / HTTP/1.1" 200 58341 "-" "curl/7.61.1"
2001:67c:1220:808::93e5:8ad - - [22/Feb/2019:08:56:10 +0100] "POST /wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500 HTTP/1.1" 200 3279 "https://ios-example.com/wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500" "WordPress/4.9.9; https://ios-example.com"
...

この形式で日付と時刻を抽出する必要があります22/Feb/2019:07:49:01

これが私が今持っているものです(このスレッドからはっきりとコピーしました:行から日付フィールドを抽出する):

file="filename"
while IFS= read -r line
do
    echo "`cut -d '[' -f2 $line | cut -d ' ' -f1`" # echoing now for testing purposes
done <"$file"

スクリプト実行時の出力は次のとおりです。

cut: '2001:67c:1220:80c:d4:985a:df2c:d717': Adresář nebo soubor neexistuje
cut: '[22/Feb/2019:07:49:01': Adresář nebo soubor neexistuje
cut: +0100]: Adresář nebo soubor neexistuje
cut: '"GET': Adresář nebo soubor neexistuje
cut: /: je adresářem
cut: 'HTTP/1.1"': Adresář nebo soubor neexistuje
cut: 200: Adresář nebo soubor neexistuje
cut: 58266: Adresář nebo soubor neexistuje
cut: '"-"': Adresář nebo soubor neexistuje
cut: '"curl/7.61.1"': Adresář nebo soubor neexistuje
22/Feb/2019:08:49:01
22/Feb/2019:08:56:10
22/Feb/2019:08:56:10
22/Feb/2019:09:24:33
22/Feb/2019:09:24:33
22/Feb/2019:09:43:13
22/Feb/2019:09:43:24
...

「Adresář nebo file existing」は、「ディレクトリやファイルが存在しません」を意味します。

私には不明な理由でログファイルの最初の行では機能しませんが、ファイルの残りの部分では機能します。

答え1

色々なミスを犯しました。

  • cut はファイル名を引数として使用します。
  • 二重引用符を忘れました()

したがって、最小限の変更でサンプルを再構築すると、次のようになります。

  • 何かの目的を指します。$(変える`。これはより強力で再帰的に機能します。
  • 何かの目的を指します。${VARIABLE_NAME}$VARIABLE_NAMEの代わりに。これはもっと頑丈です。

新バージョン

file="filename"
while IFS= read -r line
do
    EXTRACT_DATE=$( echo "$line" | cut -d '[' -f2 | cut -d ' ' -f1  )
    echo "${EXTRACT_DATE}"        
done <"$file"

答え2

エラーを引き起こす主な問題は、読み取り行をから読み取る$lineファイル名として使用していることです。cut

echoこれを使用してコマンド置換結果を出力することもできます。これはアンチパターンです。パイプラインを実行するだけです。コマンドを置き換える必要はありませんecho。結果を端末に出力します。

ここでは、次を使用してファイルから読み取った行をprintf提供します。cut

file="filename"

while IFS= read -r line; do
    printf '%s\n' "$line" | cut -d '[' -f2 | cut -d ' ' -f1
done <"$file"

次に注目すべき点は、whileループが完全に不要であることです。cut二度電話をかけました。各ラインログファイルにあります。このcutユーティリティは、独自にファイルを1行ずつ読み取ることができます。

file="filename"

cut -d '[' -f2 "$file" | cut -d ' ' -f1

または、GNUを使用することもできますgrep

grep -oP '(?<=\[)[^ ]+' "$file"

(これにより、最初のスペースの後から最初のスペースの前のすべての内容が抽出されます[。)

または標準sed

sed 's/\].*//; s/.*\[//; s/ .*//' "$file"

(これを行うと、最初の後のすべてのアイテムが削除され、]最初の後のすべてのアイテムが削除され、[スペースと残りが削除されます。)

関連:

関連情報