我正在对日志文件运行以下命令,只想获取最后一个/最新的匹配项。有时可能只有一个匹配项,有时可能有多个匹配项,这给我带来了问题,因为以下命令会返回两个匹配项:
cat "$(ls -t | head -n1)" | grep -P "(NODE1[\s\S]*TEST\s=\sPOWER[\s\S]*OUTPUT\s=\s\d+?.*\s+;?)"
>>>>> (results in)...
NODE1 2018-03-06 12:01:23
TEST = POWER
EVENT_TIME = 2018-03-06 12:01:23
OUTPUT = 12
;
NODE1 2018-03-06 12:03:23
TEST = POWER
EVENT_TIME = 2018-03-06 12:03:23
OUTPUT = 7
;
如果有多个匹配组,我需要最后一个匹配组。这可以用 grep/regex 实现吗?还是我需要将结果导入 sed/awk?如果可以,怎么做?
答案1
我向你提出这个解决方案:
cat <your_source_file> | sed -n '/NODE1/,/;/p' | tr '\n' '|' | awk -F ';' '{print $(NF-1)}'|tr '|' '\n'
sed -n '/NODE1/,/;/p'
- 找到‘NODE1’块。
tr '\n' '|'
将换行符转换为记录分隔符,因此表列将以“;”分隔。
awk -F ';' '{print $(NF-1)}'
- 打印表格的最后一列。
tr '|' '\n'
- 返回上一个视图进行记录。
awk -F ';' '{for(i=(NF-1); i>0; i--){ if($i ~ "TEST = POWER"){print $i} } }'
- 仅限“TEST = POWER”事件。
答案2
根据 Yurij 的建议,我开始研究使用tac
而不是 cat,并撤销我的grep
陈述。现在,我从下往上查看文件并抓取第一个匹配项:
tac "$(ls -t | head -n1)" | grep -m 1 -P "\d+[\s\S]*TEST\s=\sTXPOWER" | tac
答案3
我发现perl
这样更方便:
perl -lane 'if(/^NODE1 /&&($#n=-1)../^;$/){push @n,$_} END{print $_ for @n}' file
解释:
•perl
实用的提取和报告语言。
•-lane
通常对单行有用的开关。
•'
实际程序指令的开始
•if(/^NODE1 /&&($#n=-1)../^;$/)
仅考虑以 stat 开头的行开头、NODE1
后跟空格、以包含单个分号的行结尾的文本部分。
•在文本部分的开头/^NODE1 /&&($#n=-1)
重置数组。 •将文本部分中的每一行保存为名为 的数组的元素 •当整个文件都被解析后,打印保存在 中的文本部分。 •程序指令的结束。 •这是您要处理的文件的名称的占位符。@n
{push @n,$_}
@n
END{print $_ for @n}
@n
'
file