利用 awk 在 bash 脚本中使用变量

利用 awk 在 bash 脚本中使用变量

我想创建一个脚本来动态调用此 awk 命令:

awk '/2019.07.16 09:00/, /2019.07.16 10:00:/' mylog.log | awk '$3 == "-" && $4 != "-" {print $4}' | sort | uniq | wc -l

我通常会成功调用该命令,但现在我想多次执行它并更改时间范围,我在设置时间时遇到困难,以下是我尝试过的内容:

for counter in {7..7}
    do
        echo "Counter "$counter
        echo /2019.07.16 0"$counter":00/, /2019.07.16 0"$((counter+1))":00:/

        # The commented code shows unsuccessful attempts
        #awk '/2019.07.16 0"$counter":00/, /2019.07.16 "$((counter+1))":00:/' mylog.log | awk '$3 == "-" && $4 != "-" {print $4}' | sort | uniq | wc -l

        # The commented code shows unsuccessful attempts
        #startvar=0"$counter":00/,
        #echo $startvar
        #awk -v start="$startvar" '/2019.07.16 start /2019.07.16 08:00:/' mylog.log | wc -l                 
    done

你有什么提示吗?预先感谢,再见

答案1

当您使用双引号而不是单引号时,变量替换将在引号之间起作用。使用这种方法,您必须将脚本中的所有$"字符引用awk\$\"

awk "/2019.07.16 0$counter:00/, /2019.07.16 0$((counter+1)):00:/" mylog.log | ...

请注意,只有0$counter:00和的解决方案才有效。0$((counter+1)):00counter+1 < 10

如果您还想过滤两位数的小时值,可以对小时字符串使用 printf 格式:

start=$(printf "%2.2d" "$counter")
stop=$(printf "%2.2d" "$((counter+1))")

awk "/2019.07.16 $start:00:/, /2019.07.16 $stop:00:/" mylog.log | ...

如果您的实际输入数据每行都包含日期和时间,并且不需要下一小时的 00 分钟,则可以简化该模式:

awk "/2019.07.16 $start:/" mylog.log | ...

例如,应该打印从到 的start=07所有行。07:00:0007:59:59

通过这种简化,您还可以将两个awk脚本合并为一个。

awk "/2019.07.16 $start:/ && \$3 == \"-\" && \$4 != \"-\" {print \$4}" mylog.log | sort -u | wc -l

注意:sort -u给出与 相同的输出sort | uniq

为了更好的解决方案,我需要知道输入数据的确切格式。

假设日期位于第 1 列,时间位于第 2 列,您可以将数据作为awk变量传递,而无需在脚本代码中进行 shell 变量扩展awk。该解决方案允许使用单引号并避免代码注入漏洞以及脚本中的引用$或引用。"

timepattern=$(printf "^%2.2d:" "$counter")
date="2019.07.16"

awk -v date="$date" -v timepattern="$timepattern" '$1 == date && $2 ~ timepattern && $3 == "-" && $4 != "-" {print $4}' mylog.log | sort -u | wc -l

相关内容