从 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);
我将无法访问该变量。
这里的问题是该文件被处理两次,一次正确处理(尽管我的条件被忽略),另一次考虑了我的变量

答案1

由于它是每个文件的属性,因此您应该JOBID在处理任何文件的第一行时进行计算,IE什么时候FNR是1:

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 程序中的任何其他表达式相同,并且具有隐式块(IE print);它总是匹配,因为JOBID总是非空并且不是等于零的数值,所以它的块总是被处理。

相关内容