传递给awk的shell脚本变量和保存所需的双引号

时间:2016-11-30 11:12:06

标签: linux shell awk

我有一些名为ts.log的日志,看起来像

[957670][DEBUG:2016-11-30 16:49:17,968:com.ibatis.common.logging.log4j.Log4jImpl.debug(Log4jImpl.java:26)]{pstm-9805256} Parameters: []
[957670][DEBUG:2016-11-30 16:49:17,968:com.ibatis.common.logging.log4j.Log4jImpl.debug(Log4jImpl.java:26)]{pstm-9805256} Types: []
[957670][DEBUG:2016-11-30 16:50:17,969:com.ibatis.common.logging.log4j.Log4jImpl.debug(Log4jImpl.java:26)]{rset-9805257} ResultSet
[957670][DEBUG:2016-11-30 16:51:17,969:com.ibatis.common.logging.log4j.Log4jImpl.debug(Log4jImpl.java:26)]{rset-9805257} Header: [LAST_INSERT_ID()]
[957670][DEBUG:2016-11-30 16:52:17,969:com.ibatis.common.logging.log4j.Log4jImpl.debug(Log4jImpl.java:26)]{rset-9805257} Result: [731747]
[065417][DEBUG:2016-11-30 16:53:17,986:sdk.protocol.process.InitProcessor.process(InitProcessor.java:61)]query String=requestid=10547

我有一个类似

的脚本
#!/bin/bash
begin=$1
cat ts.log | awk -F '[ ,]' '{if($2 ~/^[0-2][0-9]:[0-6][0-9]:[0-6][0-9]&& $2>="16:50:17"){print $0}}'

而不是像16:50:17那样输入时间我想把$ 1的shell传递给awk所以我需要做的就是./script time:hh:mm:ss脚本看起来像

#!/bin/bash
begin=$1
cat ts.log | awk -v var=$begin -F '[ ,]' '{if($2 ~/^[0-2][0-9]:[0-6][0-9]:[0-6][0-9]&& $2>="var"){print $0}}'

但双引号必须在那里或它不会起作用。 我试过2>" \"" var" \"" 但它不起作用。 那么有没有办法保持双引号? 首选结果./script 然后从指定为$ 1的时间中提取日志。

1 个答案:

答案 0 :(得分:-1)

有很多方法可以做你想做的事。

选项1:使用包含awk程序的双引号

#!/bin/bash
begin=$1
awk -F '[ ,]'  "\$2 ~ /^..:..:../ && \$2 >= \"${begin}\" "  ts.log
  • 在双引号字符串中,bash执行变量替换。因此,$begin${begin}将替换为shell变量值(无论用户发送的是什么)
  • 不受欢迎的效果:以$开头的awk特殊变量必须使用'\'进行转义,否则bash会在执行awk之前尝试替换它们。
  • 要在bash双引号字符串中获取双引号char("),必须使用'\'进行转义,因此在bash " \"16:50\" "中将替换为"16:50" }。 (这不适用于单引号字符串,在bash中根本没有扩展变量也没有转义字符。)
  • 要查看bash执行脚本时进行的变量替换,可以使用debug选项执行它(这非常有启发性):

    $ bash -x yourscript.sh 16:50
    

选项2:使用awk变量

#!/bin/bash
begin=$1
awk -F '[ ,]' -v begin=$begin '$2 ~ /^..:..:../ && $2 >= begin'  ts.log
  • 此处使用选项begin创建了awk变量-v varname=value
  • awk变量可以在awk程序的任何地方用作任何其他awk变量(不需要双引号也不需要$)。

还有其他选择,但我认为你可以使用这两个选项。

在这两个选项中我都改变了你的脚本:

  • cat发送数据不需要awk,因为awk可以在程序之后作为参数发送的一个或多个数据文件中执行您的程序。
  • 您的awk程序根本不需要包含print(如@fedorqui所说),因为基本的awk程序由pattern {code}对组成,其中pattern与您在if句子,默认代码为{print $0}
  • 我也改变了时间模式,主要是为了澄清脚本,但是在日志文件中几乎没有机会存在一个8字符长度的字符串,内部有2个冒号(regexp:. repaces任何字符)