Perl 查找副本并在匹配项上执行脚本
我正在尝试创建一个脚本来解析日志文件,并查找每行特定部分的重复匹配项,如果存在重复项,我需要在匹配该重复项的第一行上执行一个脚本。我的日志详细信息如下:Perl 查找副本并在匹配项上执行脚本,perl,bash,grep,Perl,Bash,Grep,我正在尝试创建一个脚本来解析日志文件,并查找每行特定部分的重复匹配项,如果存在重复项,我需要在匹配该重复项的第一行上执行一个脚本。我的日志详细信息如下: #: 177 101 User 1 Channel: SIP/101 #: 178 117 User 2 Channel: SIP/117 #: 179 150 User 3 Channel: SIP/150 #: 356 166 User 4 Channel: SIP/1
#: 177 101 User 1 Channel: SIP/101
#: 178 117 User 2 Channel: SIP/117
#: 179 150 User 3 Channel: SIP/150
#: 356 166 User 4 Channel: SIP/166
#: 387 117 User 2 Channel: SIP/117
我希望根据日志文件的SIP/部分查找副本,但我需要根据日志文件的#部分执行脚本。根据这个日志,我需要为#:178行执行一个脚本
到目前为止,我已经使用了
egrep-o.{50}SIP.{4}
根据线路的SIP/区段查找重复项。我不清楚如何获得整行代码以获得#:178并生成要执行的脚本。一种方法:
grep -nE "$(sed -ne '/^#/s/.*SIP\/\([0-9]*\)$/\1/p' log.txt | sort -n | uniq -d | paste -sd '|')" log.txt | head -n 1
这将打印(基于您的示例文件):
主命令是grep-nE“$(…)”log.txt
,它将在日志文件中搜索重复的行并打印它们(该行的正则表达式是动态生成的,我将在下面解释)。然后,输出通过管道传输到头-n1
以仅打印第一行。grep
命令的-n
标志打印匹配的实际行号,如果不需要,可以将其删除
要生成正则表达式,我们有4个命令
sed-ne'/^#/s/*SIP\/\([0-9]*\)$/\1/p'log.txt
将仅提取以
开头的行上的SIP编号uniq-d
命令仅打印重复行paste
命令将所有数字连接在一行中,我们使用-d'|'
选项指定我们希望数字以'|'分隔,这是OR的正则表达式运算符希望这有帮助=)这里有一种使用GNU awk的方法:
awk '$NF in array && !dup[$NF] { print array[$NF]; dup[$NF]++ } { array[$NF]=$2 }' file.txt
结果:
178
一次性解决方案。它利用了
uniq
支持跳过字段和仅重复标记的优势
sed -n '/SIP/{s/^#:\s\+\([0-9]\+\).*SIP\/\([0-9]\+\)/\1 \2/;p}' file.txt | sort -k2,2 -n | uniq -f 1 -d | cut -f1 -d ' '
AWK对这类事情很有效 这是一个可读的一次性解决方案
#!/usr/bin/env awk -f
{
sip = $3
script = $2
count[sip]++
if (count[sip] == 1) {
scripts[sip] = script
}
else if (count[sip] > 1) {
to_run[sip] = scripts[sip]
}
}
END {
for (sip in to_run) {
print to_run[sip]
}
}
当我运行您的命令时,它返回
#:177 101 User 1 Channel:SIP/101
。您是如何运行它的?您是否创建了一个带有OP示例精确副本的log.txt
文件?我觉得奇怪的是,从line=SYes的开头就缺少了原始行号log.txt与OP的日志文件完全相同。您应该能够一次完成此操作-在每个记录上,检查是否存在相应的数组项,并在设置数组值之前打印它,并添加第二个数组,用于跟踪条目是否已打印(以避免在第三次和后续出现时再次打印).Good idea=)我可以建议添加-n
标志进行排序吗?另一个小建议:可能在sed的替换命令中使用p
标志,并使用-n
命令行选项?这是泛化并忽略与模式不匹配的行。
#!/usr/bin/env awk -f
{
sip = $3
script = $2
count[sip]++
if (count[sip] == 1) {
scripts[sip] = script
}
else if (count[sip] > 1) {
to_run[sip] = scripts[sip]
}
}
END {
for (sip in to_run) {
print to_run[sip]
}
}