我想选择在可选字符之后捕获两个组。 我有2种可能的数据输出,如下所示:
Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Server is unavailable
Subject: 2019.07.19 13:28:29 some.host.com 178892 Problem: Server is unavailable; Resolved: 2019.07.19 14:49:29
我的正则表达式过滤器如下:
"/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[0-9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) Problem\: (.*)/"
到目前为止,它的工作方式如下:
\1 = 2019.07.19
\2 = 13:30:00
\3 = some.host.com
\4 = 178899
\5 = Server is unavailable
第二种模式:
\1 = 2019.07.19
\2 = 13:30:00
\3 = some.host.com
\4 = 178899
\5 = Server is unavailable; Resolved: 2019.07.19 14:49:29
我按如下方式使用此正则表达式过滤器:
echo "$SUBJECT" | sed -E "s/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[0-9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) Problem\: (.*)/\1\2\3\4\5/"
我想要的是\ 5组仅文本,直到可选的“;”字符,因此它将是“服务器不可用” 并且在可选“;”的情况下字符,然后同时捕获\ 6和\ 7以分别返回“ 2019.07.19”和“ 14:49:29”。
几个小时以来,我一直在尝试与非捕获组和可选组一起玩,但没有任何效果。
有人可以帮助我解决这一具有挑战性的问题吗?
更新:
PROBLEM_DATE=output[0]
PROBLEM_TIME=output[1]
PROBLEM_HOST=output[2]
PROBLEM_ID=output[3]
PROBLEM_DESC=output[4]
RESOLVED_DATE=output[5]
RESOLVED_TIME=output[6]
,然后可能会处理此数据,比较时间并写入日志文件。
Update2:
如果可以简化事情,我可以稍微调整一下数据格式。 是的,也许我在处理复杂的事情时,也许最好重新格式化:
Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Server is unavailable
Subject: 2019.07.19 13:28:29 some.host.com 178892 Problem: Server is unavailable; Resolved: 2019.07.19 14:49:29
对此:
Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Server is unavailable
Subject: 2019.07.19 14:49:29 some.host.com 178892 Resolved: Server is unavailable
我知道,我尝试做的方法不正确。
所以我想我可以将以下正则表达式与新数据格式一起使用:
"/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[0-9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) (?:Problem|Resolved)\: (.*)/"
我不确定结构“(?:Problem | Resolved)”是否正确。
然后检查字符串是否包含单词“问题”或“已解决”以根据事件采取措施。
如果我将其分配给变量,sed不会给我数组输出吗? 我现在无法访问我的linux终端,因此无法检查。
答案 0 :(得分:0)
这可能对您有用(GNU sed):
sed -E 's/^Subject: (....\...\...) (..:..:..) (\S+) (\S+) Problem: ([^;]*)(; Resolved: (....\...\...) (..:..:..))?.*/PROBLEM_DATE=\1\nPROBLEM_TIME=\2\nPROBLEM_HOST="\3"\nPROBLEM_ID=\4\nPROBLEM_DESC="\5"\nRESOLVED_DATE=\7\nRESOLVED_TIME=\8/' <<<"$SUBJECT" >srcFile
. scrFile
使用模式匹配和向后引用将所需结果输出到文件,然后将该文件作为源。
反向引用7和8分组在反向引用6中,后者是可选的(?)。
答案 1 :(得分:0)
我不确定我是否理解您的问题,但这就是您要尝试做的(使用GNU awk将第三个参数匹配到():
$ cat tst.awk
match($0,/Subject: ([2-9]{1}[0-9]{3}(\.[0-9]{2}){2}) ([0-9]{2}(:[0-9]{2}){2}) ([[:alnum:]._-]+) ([0-9]+) (Problem|Resolved): (.*)/,a) {
print "PROBLEM_DATE=" a[1]
print "PROBLEM_TIME=" a[3]
print "PROBLEM_HOST=" a[5]
print "PROBLEM_ID=" a[6]
print "PROBLEM_STATE=" a[7]
print "PROBLEM_DESC=" a[8]
print "---"
}
$ awk -f tst.awk file
PROBLEM_DATE=2019.07.19
PROBLEM_TIME=13:30:00
PROBLEM_HOST=some.host.com
PROBLEM_ID=178899
PROBLEM_STATE=Problem
PROBLEM_DESC=Server is unavailable
---
PROBLEM_DATE=2019.07.19
PROBLEM_TIME=14:49:29
PROBLEM_HOST=some.host.com
PROBLEM_ID=178892
PROBLEM_STATE=Resolved
PROBLEM_DESC=Server is unavailable
---
以上操作是在此输入文件上执行的:
$ cat file
Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Server is unavailable
Subject: 2019.07.19 14:49:29 some.host.com 178892 Resolved: Server is unavailable
您说过要比较时间戳,并根据结果将其写入日志文件-只需在awk中完成所有操作,请勿尝试在shell中进行操作。
答案 2 :(得分:-2)
我刚刚找到了解决方案。 sed输出配置为“ \ 1 | \ 2 | \ 3 |”它将产生一个定界的字符串,然后我将字符串简单地用“ |”分割字符以获取数组,可以将其与正确的数组成员计数进行比较,然后将它们分配给适当的变量以供以后进行可能的处理。
#!/bin/bash
SUBJECT="Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Server is unavailable"
OUTPUT=`echo "$SUBJECT" | sed -E 's/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[0-
9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) Problem\: (.*)/\1|\2|\3|\4|\5|/'`
echo "OUTPUT = $OUTPUT"
IFS='|'
read -a RESULT <<< "$OUTPUT"
echo "${RESULT[0]}"
echo "${RESULT[1]}"
echo "${RESULT[2]}"
echo "${RESULT[3]}"
echo "${RESULT[4]}"
输出:
sh-4.4$ ./test.sh
OUTPUT = 2019.07.19|13:30:00|some.host.com|178899|Server is unavailable|
2019.07.19
13:30:00
some.host.com
178899
Server is unavailable
Update-1:
按照建议将解释器从...
更改为$(...),甚至更好-用双引号将它们引起来。
OUTPUT="$(echo "$SUBJECT" | sed -E 's/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[
0-9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) Problem\: (.*)/\1|\2|\3|\4|\5|/')"
可以改进的是-用定界符|将字符串拆分为数组的方式。我现在正在寻找一种更好的方法,将尽快更新答案。
Update-2:
这是所需的解决方案。实际上有一个更大的脚本。这只是一部分。它可以正常工作并满足我的要求。
#!/bin/bash
SUBJECT="Subject: 2019.07.19 13:30:00 some.host.com 178899 Problem: Resolved: Server Problem:is unavailable"
OUTPUT="$(echo "$SUBJECT" | sed -E 's/Subject\: ([2-9]{1}[0-9]{3}\.[0-9]{2}\.[0-9]{2}) ([0-9]{2}\:[0-9]{2}\:[
0-9]{2}) ([a-zA-Z0-9._-]*) ([0-9]*) (Problem|Resolved)\: (.*)/\1|||\2|||\3|||\4|||\5|||\6/')"
IFS='|||'
read -a RESULT <<< "$OUTPUT"
if [ "${#RESULT[*]}" -eq '16' ];
then
EVENT_DATE="${RESULT[0]}"
EVENT_TIME="${RESULT[3]}"
EVENT_HOST="${RESULT[6]}"
EVENT_ID="${RESULT[9]}"
EVENT_TYPE="${RESULT[12]}"
EVENT_TEXT="${RESULT[15]}"
echo "EVENT_DATE: $EVENT_DATE"
echo "EVENT_TIME: $EVENT_TIME"
echo "EVENT_HOST: $EVENT_HOST"
echo "EVENT_ID: $EVENT_ID"
echo "EVENT_TYPE: $EVENT_TYPE"
echo "EVENT_TEXT: $EVENT_TEXT"
fi
和输出:
EVENT_DATE: 2019.07.19
EVENT_TIME: 13:30:00
EVENT_HOST: some.host.com
EVENT_ID: 178899
EVENT_TYPE: Problem
EVENT_TEXT: Resolved: Server Problem:is unavailable