awkのFILENAMEから値を抽出して新しいフィールドとして使用する

awkのFILENAMEから値を抽出して新しいフィールドとして使用する

私はEvent_42417555_2018-05-23_16\:45\:28-log.txt次のような名前と形式のCSVファイルで作業しています。

timestamp;fullpath;event;size
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_OPEN;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_ACCESS;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_CLOSE_NOWRITE;2324
1521540649.02;/home/workdir/quad_list_14.json;IN_OPEN;2160
1521540649.03;/home/workdir/quad_list_14.json;IN_ACCESS;2160
1521540649.03;/home/workdir/quad_list_14.json;IN_CLOSE_NOWRITE;2160

私が望むのは、正規表現を使用して抽出されたファイル名の値に基づいてファイルに列を追加し、[0-9]{8}ヘッダーを削除することです。

1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_OPEN;2324;42417555
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_ACCESS;2324;42417555
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_CLOSE_NOWRITE;2324;42417555
1521540649.02;/home/workdir/quad_list_14.json;IN_OPEN;2160;42417555
1521540649.03;/home/workdir/quad_list_14.json;IN_ACCESS;2160;42417555
1521540649.03;/home/workdir/quad_list_14.json;IN_CLOSE_NOWRITE;2160;42417555

Gnuツールを使用すると、次のように簡単に表示されます(ほとんどテストされておらず、ほぼ確実に引用符の問題です)。

#!/bin/bash
#$1 being the filename
JOBID=$(grep -oE "[0-9]{8}" "${1}")
sed -E "s/(.*)/\1;$JOBID/" "${1}"

私はawkこれまで効果があったことでこれを達成したいと思います。最高:

awk -F";"  'JOBID=substr(FILENAME ,match(FILENAME,"[0-9]{8}"),8); \  
BEGIN { OFS=";"} { if ($1 != "timestamp") print $0,JOBID; }' \  
Event_42417555_2018-05-23_16\:45\:28-log.txt | head

timestamp;fullpath;event;size
timestamp;fullpath;event;size
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_OPEN;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_OPEN;2324;42417555
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_ACCESS;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_ACCESS;2324;42417555
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_CLOSE_NOWRITE;2324
1521540649.02;/home/workdir/ScienceXMLIn/config.cfg;IN_CLOSE_NOWRITE;2324;42417555

変数があり、正しく設定されていますが、正しい場所が見つかりません。
移動するとJOBID=substr(FILENAME ,match(FILENAME,"[0-9]{8}"),8);
変数にアクセスできなくなります。
ここで問題は、ファイルが2回処理されることです。一度は正しく処理され(私の条件は無視されますが)、もう一度は私の変数を考慮します。

ベストアンサー1

ファイル固有の属性なので、ファイルJOBIDの最初の行を処理するときに計算する必要があります。つまり1はいつFNRですか?

awk -F";" 'BEGIN { OFS = FS }
FNR == 1 { JOBID=substr(FILENAME, match(FILENAME, "[0-9]{8}"), 8); print }
FNR > 1 { print $0, JOBID }' \
Event_42417555_2018-05-23_16\:45\:28-log.txt | head

正規表現の一致を抽出する方法はいくつかあります。私は通常match配列を使用します。

awk -F";" 'BEGIN { OFS = FS }
FNR == 1 { match(FILENAME, "([0-9]{8})", a); JOBID = a[1]; print }
FNR > 1 { print $0, JOBID }' \
Event_42417555_2018-05-23_16\:45\:28-log.txt | head

エラー処理機能を備えた方が良いです。これはmatch、テキスト一致を検索し、[0-9]{8}一致する値を配列に抽出するために使用されますamatchグループを見つけるため、括弧が追加されます)。

AWK 実装で動作する別の方法は、ファイル名をアンダースコアに分割することです。

awk -F";" 'BEGIN { OFS = FS }
FNR == 1 { split(FILENAME, a, "_"); JOBID = a[2]; print }
FNR > 1 { print $0, JOBID }' \
Event_42417555_2018-05-23_16\:45\:28-log.txt | head

あなたのバージョンの二重出力は、JOBID=substr(FILENAME ,match(FILENAME,"[0-9]{8}"),8)AWKプログラムの他の式と同じ重みを持つ完全な式であり、暗黙のブロック(つまり print);JOBID常に空ではなく、ゼロなどの数値ではないため、常に一致するため、対応するチャンクは常に処理されます。

おすすめ記事