0

I am trying to write a little bash script, where you can specify a number of minutes and it will show the lines of a log file from those last X minutes. To get the lines, I am using sed

sed -n '/time/,/time/p' LOGFILE

On CLI this works perfectly, in my script however, it does not.

# Get date
now=$(date "+%Y-%m-%d %T")

# Get date minus X number of minutes -- $1 first argument, minutes
then=$(date -d "-$1 minutes" +"%Y-%m-%d %T")

# Filter logs -- $2 second argument, filename
sed -n '/'$then'/,/'$now'/p' $2

I have tried different approaches and none of them seem to work:

result=$(sed -n '/"$then"/,/"$now"/p' $2)
sed -n "/'$then'/,/'$now'/p" "$2"
sed -n "/$then/,/$now/p" $2
sed -n "/$then/,/$now/p" "$2

Any sugesstions? I am on Debian 5, echo $SHELL says /bin/sh

EDIT : The script produces no output, so there is no error showing up. In the logfile every entry starts with a date like this 2013-05-15 14:21:42,794

4

2 回答 2

1

我认为主要问题是您尝试通过字符串匹配来执行算术比较。sed -n '/23/,/27/p'为您提供包含的第一行23和包含的下一行之间的行27(然后再次从包含的下一行到包含23的下一行,27依此类推)。它不会您提供包含 23 到 27 之间数字的所有行。如果输入看起来像

19
22
24
26
27
30

它不输出任何东西(因为没有23)。使用字符串匹配的 awk 解决方案也有同样的问题。因此,除非您的then日期字符串逐字出现在日志文件中,否则您的方法将失败。您必须将日期字符串转换为数字(删除-<space>:),然后使用算术比较而不是字符串匹配来检查结果数字是否在正确的范围内。这超出了 sed 的能力;awk 和 perl 可以很容易地做到这一点。这是一个perl解决方案:

#!/bin/bash

NOW=$(date "+%Y%m%d%H%M%S")
THEN=$(date -d "-$1 minutes" "+%Y%m%d%H%M%S")

perl -wne '
  if (m/^(....)-(..)-(..) (..):(..):(..)/) {
    $date = "$1$2$3$4$5$6";
    if ($date >= '"$THEN"' && $date <= '"$NOW"') {
      print;
    }
  }' "$2"
于 2013-05-15T17:23:43.657 回答
1

不要让嵌套引号让自己头疼。使用-vwith 选项awk将 shell 变量的值传递到脚本中:

#!/bin/bash

# Get date
now=$(date "+%Y-%m-%d %T")

# Get date minus X number of minutes -- $1 first argument, minutes
delta=$(date -d "-$1 minutes" +"%Y-%m-%d %T")

# Filter logs -- $2 second argument, filename
awk -v n="$now" -v d="$delta" '$0~n,$0~d' $2

也不要使用 shell 内置函数的变量名,即then.

于 2013-05-15T12:01:37.130 回答