我有一个日志文件,其格式非常一致并且由我控制。它生成长度恒定的管道分隔字段。
有两个字段与我希望创建的过滤过程相关,将它们称为主要字段和次要字段。
使用 Grep 我可以首先过滤主要内容。这将产生相关行的不完整列表。在此列表中将显示几行,这些行在辅助字段中将具有两个不同值之一。还会有其他行与主字段不匹配,但其主字段为空白,与一个或另一个辅助字段值匹配。所有这些行都是相关的。我希望它们出现在最终输出中,但直到完成初始阶段我才知道它们。
次要字段匹配的所有条目将具有初始主要字段或空白主要字段。在任何情况下,辅助字段都不会为空。
我的策略是 1. awk 一次日志文件,取出主字段匹配的所有行(这将是脚本的输入)。对于每个这样的行,检查辅助字段,直到找到两个可能匹配的辅助字段值。 2. 再次 awk 日志文件,取出主字段匹配或辅助字段与第一遍中学到的两个值之一匹配的所有行。
如何存储在第 1 轮中学到的两个辅助字段值,然后使用它们编写第 2 轮的条件?
我被要求提供示例,因此这里是说明要点的数据的简化版本。 “主要”是字段 2,“次要”是字段 3。
这是第一次拉取(输入值为05478900172)
2015-03-10 09:13:40,598|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,617|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,617|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,626|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,626|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:14:16,686|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,695|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,705|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,705|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,714|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,714|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:23,838|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,878|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,878|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S| 0
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,888|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,888|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:15:01,915|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,936|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,936|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,945|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,946|05478900172|4792761 | 17|s|D|S|----
由此我们可以看到,辅助字段 ($3) 包含该主字段的两个可能值(4792761 或 4792964)。
我们希望我们的脚本提取以下数据集,其中包含 $2 中包含 05478900172 的所有记录以及 $3 中包含(4792761 或 4792964)的所有记录。在完成初始扫描之前我不知道这两个值,因此我需要将这些值作为变量传递,这些变量以某种方式在第一遍和第二遍之间共享。
2015-03-10 09:13:40,598|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,601|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,608| null|4792761 |---|-|K|-|----
2015-03-10 09:13:40,608| null|4792761 |---|-|K|-|----
2015-03-10 09:13:40,617| null|4792761 |---|r|D|S|----
2015-03-10 09:13:40,617|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,617|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,626|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:13:40,626|05478900172|4792761 | 15|s|D|S|----
2015-03-10 09:14:16,686|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,694|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,695|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,696| null|4792964 |---|-|K|-|----
2015-03-10 09:14:16,696| null|4792964 |---|-|K|-|----
2015-03-10 09:14:16,704| null|4792964 |---|r|D|S|----
2015-03-10 09:14:16,705|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,705|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,714|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,714|05478900172|4792964 | 41|s|D|S|----
2015-03-10 09:14:16,760| null|4792964 |---|r|D|S|----
2015-03-10 09:14:16,760| null|4792964 |---|r|D|S|----
2015-03-10 09:14:23,817| null|4792964 | 42|-|D|S|----
2015-03-10 09:14:23,817| null|4792964 | 42|-|D|S|----
2015-03-10 09:14:23,817| null|4792964 | 42|-|D|S|7057
2015-03-10 09:14:23,817| null|4792964 | 42|-|D|S|----
2015-03-10 09:14:23,818| null|4792964 | 42|-|D|S|----
2015-03-10 09:14:23,818| null|4792964 | 42|-|D|S|----
2015-03-10 09:14:23,838|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,876| null|4792964 |---|-|K|-|----
2015-03-10 09:14:23,876| null|4792964 |---|-|K|-|----
2015-03-10 09:14:23,878|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,878|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,878| null|4792964 |---|r|D|S|----
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,879| null|4792964 |---|r|D|S|----
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S| 0
2015-03-10 09:14:23,879|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,888|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:14:23,888|05478900172|4792964 | 43|s|D|S|----
2015-03-10 09:15:01,915|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,917|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,925| null|4792761 |---|-|K|-|----
2015-03-10 09:15:01,925| null|4792761 |---|-|K|-|----
2015-03-10 09:15:01,936| null|4792761 |---|r|D|S|----
2015-03-10 09:15:01,936|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,936|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,945|05478900172|4792761 | 17|s|D|S|----
2015-03-10 09:15:01,946|05478900172|4792761 | 17|s|D|S|----
答案1
根据@KM的要求,这是我的答案。
#! /bin/sh
# this script pulls all rows from a log that are directly or
# indirectly related to a given session id. Session IDs are stored
# in $2 of each row. This field may be null. Directly related
# rows are those with $2 matching the supplied parameter. Indirectly
# related rows are those with $3 (aka xid) matching $3 in some other
# row where $2 matches the supplied parameter.
# It may be assumed that for any rows with the same $3,
# the $2 field will be identical or null.
SESS_SRCH="$1"
if [ -z $2 ]
then
LOGFILE=/path/to/default/log
else
LOGFILE=$2
fi
# pass 1:
# read the logfile once to find all unique XIDs associated
# with the supplied session ID ($SESS_SRCH)
XIDS=$(awk -F\| -v sessid="$1" '$2 ~ sessid { xids[$3]=0 }
END{
for (xid in xids) {
print xid
}
}' < ${LOGFILE}
)
XID_SRCH=""
#build a search string from these xids to form a new search string.
for XID in $XIDS
do
XID_SRCH="${XID_SRCH}|${XID}"
done
#strip off the leading "|"
XID_SRCH=${XID_SRCH:1}
# pass 2
# read the logfile again, this time seaching on $3, for any of the
# xids found in pass 1.
awk -F\| -v search="$XID_SRCH" '$3 ~ search { print }' < ${LOGFILE}
答案2
这是一些代码片段,应该满足您的要求,尽管在我看来,问题是一个逻辑问题,因为无论是否进行第二次测试,该循环的输出都是相同的,因为无论何时都会发生匹配。我猜您需要在第二次运行 awk 时进行比您描述的更复杂的测试。
此代码片段的作用是首先提取数据文件中与字段 2 匹配的所有行,并提取字段 3,然后通过使用排序和 uniq 消除字段 3 的重复项。然后对每个 uniq 字段 3 值运行 while 循环(4792761 或 4792964),但这次针对 PATTERN 测试字段 2,针对循环值测试字段 3。
PATTERN="05478900172"
awk -F\| -v matchpat="$PATTERN" '$2 ~ matchpat {print $3}' | sort | uniq | while read field
do
awk -F\| -v matchpat=$PATTERN -v secondpat="$field" '$2 ~ matchpat { if ( $3 ~ secondpat ) {print $0}}' datafile
done
现在我猜你确实想做一些比你描述的更复杂的事情,因为你可以通过使用字段 3 作为排序键对第一个 awk 命令的输出进行排序来简化它并消除 while 循环。