解析一条awk命令

问题

解决向日葵后台进程异常日志时发现一条awk命令。

awk -F '=' '/\[common\]/{a=1}a==1&&$1~/autorun/{print $2;exit}' /etc/orayconfig.conf

介绍

使用 awk --help 查看awk使用方法

用法:awk [POSIX 或 GNU 风格选项] -f 脚本文件 [--] 文件 ...
用法:awk [POSIX 或 GNU 风格选项] [--] '程序' 文件 ...
POSIX 选项:            GNU 长选项:(标准)
        -f 脚本文件             --file=脚本文件
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
短选项:                GNU 长选项:(扩展)
        -b                      --characters-as-bytes
        -c                      --traditional
        -C                      --copyright
        -d[文件]                --dump-variables[=文件]
        -D[文件]                --debug[=文件]
        -e '程序文本'            --source='程序文本'
        -E 文件                 --exec=文件
        -g                      --gen-pot
        -h                      --help
        -i 包含文件             --include=包含文件
        -l 库           --load=库
        -L[fatal|invalid|no-ext]        --lint[=fatal|invalid|no-ext]
        -M                      --bignum
        -N                      --use-lc-numeric
        -n                      --non-decimal-data
        -o[文件]                --pretty-print[=文件]
        -O                      --optimize
        -p[文件]                --profile[=文件]
        -P                      --posix
        -r                      --re-interval
        -s                      --no-optimize
        -S                      --sandbox
        -t                      --lint-old
        -V                      --version

To report bugs, see node `Bugs' in `gawk.info'
which is section `Reporting Problems and Bugs' in the
printed version.  This same information may be found at
https://www.gnu.org/software/gawk/manual/html_node/Bugs.html.
PLEASE do NOT try to report bugs by posting in comp.lang.awk,
or by using a web forum such as Stack Overflow.

gawk 是一个模式扫描及处理语言。缺省情况下它从标准输入读入并写至标准输出。

Examples:
        awk '{ sum += $1 }; END { print sum }' file
        awk -F: '{ print $1 }' /etc/passwd

现在我们可以将原命令拆分为4块

序号 语句块 解析
1 awk awk 程序本身
2 -F '=' 指定以 = 为分隔符处理文件每一行
3 '/\[common\]/{a=1}a==1&&$1~/autorun/{print $2;exit}' awk 的程序参数
4 /etc/orayconfig.conf awk 的输入文件

1、2和4比较简单,难点在于3,awk 的程序参数解析

程序

使用man gawk查看awk帮助文档。

AWK PROGRAM EXECUTION
       An AWK program consists of a sequence of optional directives, pattern-action statements, and optional function definitions.

              @include "filename"
              @load "filename"
              @namespace "name"
              pattern   { action statements }
              function name(parameter list) { statements }

程序部分支持以上五种格式,显然我们的程序属于第4种,pattern + action

即原命令有如下两个程序:

序号 原语句 pattern action
1 /\[common\]/{a=1} /\[common\]/ a=1
2 a==1&&$1~/autorun/{print $2;exit} a==1&&$1~/autorun/ print $2;exit

他们的先后顺序如何呢?不着急,我们继续看man文档。

For each record in the input, gawk tests to see if it matches any pattern in the AWK program. For each pattern that the record matches, gawk executes the associated action. The patterns are tested in the order they occur in the program.

依照出现的顺序依次匹配 pattern,并在匹配成功时执行 action

这个描述中 p2a1 的先后顺序并不明确,写了一个测试用例,发现执行顺序为: p1 -> a1 -> p2 -> a2

结论

#!/bin/env bash

awk                          \
    -F '='                   \
    '/\[common\]/            \
    { a = 1 }                \
    a == 1 && $1 ~ /autorun/ \
    { print $2; exit }'      \
    /etc/orayconfig.conf

这条命令读取/etc/orayconfig.conf文件,对于文件每一行优先匹配/[common],匹配成功后定义变量a并赋值为1;然后再判断a值是否为1(即已经匹配过[common])并且以=为分隔符的第一个参数是否匹配autorun,如果匹配成功,打印第二个参数,然后结束整个程序。

整条命令解析 orayconfig.conf 配置文件,解析并获取common域的autorun值并返回。

探索

这个命令到此已经解析完成了,那么它能够完美解决需求么,是否存在一些隐患呢?

  1. 只要匹配过[common],a值恒为1,程序有可能解析到common之后某个域内的autorun值。
  2. 程序中的正则匹配没有开始符号和结束符号,有可能解析到包含autorun的配置项,例如:daemonautorun。

优化

优化后的命令如下,只检查 common 域,并在 common 域结束后停止程序。

#!/bin/env bash

awk                                 \
    -F '='                          \
    '/^\[common\]$/                 \
    { common = 1 }                  \
    common == 1 && $1 ~ /^autorun$/ \
    { print $2; exit }              \
    common == 1 && /^\[/            \
    { exit }'                       \
    /etc/orayconfig.conf

你可能感兴趣的:(linux,awk)