我想提取两个不同的相对时间戳之间的行,我写了一个bash脚本,但它不能正常工作;请告诉我怎样才能做得正确。
我的日志文件看起来像这样:
22/06/23 19:30:21 [Logs...]
22/06/24 17:58:30 [Logs...]
22/06/24 17:59:48 [Logs...]
22/06/24 18:11:27 [Logs...]
22/06/24 18:11:28 [Logs...]
不能正常工作的代码:
命令:./test.sh -t 22/06/24,17:58:00-22/06/24,18:11:59
代码:
#! /bin/bash
#INPUT: 22/06/24,17:58:00-22/06/24,18:11:30
#startDate=22/06/24
startDate=$(echo $2 | cut -d "-" -f 1 | cut -d "," -f 1)
#endDate=22/06/24
endDate=$(echo $2 | cut -d "-" -f 2 | cut -d "," -f 1)
#startTime=17:58:00
startTime=$(echo $2 | cut -d "-" -f 1 | cut -d "," -f 2)
#endTime=18:11:30
endTime=$(echo $2 | cut -d "-" -f 2 | cut -d "," -f 2)
#Script Parameter Format to search in Log Files: YY/MM/DD hh:mm:ss-YY/MM/DD hh:mm:ss
#timestampStart=22-06-24 17:58:00
timestampStart=$(echo $startDate | cut -d "/" -f 1)-$(echo $startDate | cut -d "/" -f 2)-$(echo $startDate | cut -d "/" -f 3)" "$startTime
#timestampEnd=22-06-24 18:11:27
timestampEnd=$(echo $endDate | cut -d "/" -f 1)-$(echo $endDate | cut -d "/" -f 2)-$(echo $endDate | cut -d "/" -f 3)" "$endTime
#tstart=1656077280
tStart=`date --date="$timestampStart" +%s`
#tEnd=1656078090
tEnd=`date --date="$timestampEnd" +%s`
while read -r line; do
re="[0-9]{2}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}"
if [[ $line =~ $re ]]; then
#searchDate="22/06/24 17:58:00"
searchDate=$(echo $line | cut -d " " -f 1,2)
#searchTime="22-06-24 17:58:00"
searchTime=$(echo $searchDate | cut -d "/" -f 1)-$(echo $searchDate | cut -d "/" -f 2)-$(echo $searchDate | cut -d "/" -f 3)
#tSearch=1656077280
tSearch=`date --date="$searchTime" +%s`
fi
#if 1656077280>=1656077280 AND 1656077280<=1656078090
if [ $tSearch -gt $tStart ] && [ $tSearch -lt $tEnd ];then
#22/06/24 17:58:00 at java.lang.Integer.parseInt(Integer.java:542)
echo $line
fi
done < /oracleAS10g/product/opmn/logs/OC4J~officeauto~default_island~1
输出错误:
./test.sh: line 43: [: -gt: unary operator expected
预期输出:显示指定
的两个时间戳之间的行22/06/24 17:58:30 [Logs...]
22/06/24 17:59:48 [Logs...]
22/06/24 18:11:27 [Logs...]
使用sed
可以进行精确的模式匹配,但是对于比较大于';或者"小于",您可能会发现使用grep
或awk
更容易。例如,给定输入(日期&时间,TAB分隔时间戳和日志条目):
$ cat foo.txt
22/06/23 19:30:21 [Logs ... 5]
22/06/24 17:58:30 [Logs ... 4]
22/06/24 17:59:48 [Logs ... 3]
22/06/24 18:11:27 [Logs ... 2]
22/06/24 18:11:28 [Logs ... 1]
您可以使用sed
,如另一个答案所示(通过比较,我将扩展到awk
):
$ sed -n '#22/06/24 17:58:30#, #22/06/24 18:11:27#p' foo.txt
22/06/24 17:58:30 [Logs ... 4]
22/06/24 17:59:48 [Logs ... 3]
22/06/24 18:11:27 [Logs ... 2]
基本上是:
$ sed -n '/pattern1/, /pattern2/p' file.txt
注意需要将/pattern1/, /pattern2/
更改为允许在搜索模式中使用斜杠(/
)的内容的棘手部分。选择一个最适合您的数据的。我在这里使用#
。
使用awk
大致相同,除了允许/
在搜索模式中略有不同;
$ awk -F't' '/pattern1/, /pattern2/' file.txt
变成,为了允许/
出现在模式中:
$ awk -F't' '$0~v1, $0~v2' v1="pattern1" v2="pattern2" file.txt
但是这只是匹配两个模式之间的行,并且模式必须完全匹配。我们可以将时间戳视为字母数字模式,并匹配"大于"的行。pattern1
直到<<;pattern2
:
$ awk -F't' '$1>=v1 && $1<=v2' v1="22/06/24 17:58:30" v2="22/06/24 18:11:27" foo.txt
22/06/24 17:58:30 [Logs ... 4]
22/06/24 17:59:48 [Logs ... 3]
22/06/24 18:11:27 [Logs ... 2]
但它是一个字母数字比较,所以你可以使用其他日期,如搜索模式:
$ awk -F't' '$1>=v1 && $1<=v2' v1="22/06/24 00:00:00" v2="22/06/24 18:00:00" foo.txt
22/06/24 17:58:30 [Logs ... 4]
22/06/24 17:59:48 [Logs ... 3]
你可以把>=
和<=
切换到简单的>
和<
,这取决于你是否想要包含给定的日期。
看起来像一个简单的awk
就可以完成这里的工作:
awk -v d1="22/06/24 17:58:30" -v d2="22/06/24 18:11:30" '
($1 " " $2) >= d1 && ($1 " " $2) <= d2' file
22/06/24 17:58:30 [Logs...]
22/06/24 17:59:48 [Logs...]
22/06/24 18:11:27 [Logs...]
22/06/24 18:11:28 [Logs...]