高级AWK格式

时间:2015-12-22 14:30:35

标签: bash awk

我在使用此awk命令时遇到问题。它不会产生我想要给出这个输入文件的结果。请有人帮我这个吗?

我正在寻找"班级:"价值" ABC"。当我找到ABC时。我喜欢将与userName / servicelist / hostlist和端口号关联的值分配给变量。 (请参阅输出部分)

   awk -v q="\"" '/ABC/{f=1;c++} 
   f && /userName|serviceList|hostList|portNumber/
                                 {sub(":",c"=",$1); 
                                 print $1 q $3 q
                                } 
                          /port:/{f=0;print ""}' filename

该文件包含以下输入

                      Instance: Ths is a test 
                           Class: ABC
Variables:
          udpRecvBufSize:          Numeric:          8190000
                userName:           String:test1
            pingInterval:          Numeric:                2
      blockedServiceList:           String:
       acceptAllServices:          Boolean:            False
             serviceList:           String:          ABC
                hostList:           String:    159.220.108.3
                protocol:           String:             JJJJ
             portNumber:          Numeric:            20001
                    port:           String:         RTR_LLLL
                             Children:


                          Instance: The First Server in the Loop 
                              Class: Servers
Variables:
                 pendout:          Numeric:                0
               overflows:          Counter:                0
         peakBufferUsage:          Numeric:              100
        bufferPercentage:            Gauge:                1 (0,100)
      currentBufferUsage:          Numeric:                1
         pendingBytesOut:          Numeric:                0
          pendingBytesIn:          Numeric:                1
           pingsReceived:          Counter:            13597
               pingsSent:          Counter:            87350
     clientToServerPings:          Boolean:             True
     serverToClientPings:          Boolean:             True
         numInputBuffers:          Numeric:               10
        maxOutputBuffers:          Numeric:              100
 guaranteedOutputBuffers:          Numeric:              100
      lastOutageDuration:           String:       0:00:00:00
      peakDisconnectTime:           String:
     totalDisconnectTime:           String:       0:00:00:00
          disconnectTime:           String:
       disconnectChannel:          Boolean:            False
      enableDacsPermTest:          Boolean:            False
          enableFirewall:          Boolean:            False
          dacsPermDenied:          Counter:                0
              dacsDomain:           String:
      compressPercentage:            Gauge:                0 (0,100)
     uncompBytesSentRate:            Gauge:                0    (0,9223372036854775807)





                           Instance: Ths is a test 
                               Class: ABC
Variables:
          udpRecvBufSize:          Numeric:          8190000
                userName:           String:test2
            pingInterval:          Numeric:                4
      blockedServiceList:           String:
       acceptAllServices:          Boolean:            False
             serviceList:           String:          DEF
                hostList:           String:    159.220.111.2
                protocol:           String:             ffff
              portNumber:          Numeric:            20004
                    port:           String:         JJJ_LLLL
                             Children:

这是我要找的输出。分配变量

userName1="test1"
serviceList1="ABC"
hostList1="159.220.108.3"
portNumber1="2001"

userName2="test2"
serviceList2="DEF"
hostList2="159.220.111.2"
portNumber2="2004"

4 个答案:

答案 0 :(得分:2)

如果您打算分配一系列变量,那么您可以一次性提取您感兴趣的特定部分,而不是一次解析整个文件。例如:

$ awk -F'\n' -v RS= -v record=1 -v var=userName 'NR == record { for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i }' file
test1
$ awk -F'\n' -v RS= -v record=1 -v var=serviceList 'NR == record { for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i }' file
ABC

awk脚本可以放在shell函数中并像这样使用:

parse_file() {
    record=$1
    var=$2
    file=$3

    awk -F'\n' -v RS= -v record="$record" -v var="$var" 'NR == record {
        for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i 
    }' "$file"
}

userName1=$(parse_file 1 userName file)
serviceList1=$(parse_file 1 serviceList file)
# etc.

答案 1 :(得分:0)

$ awk -F: -v q="\"" '/Class: ABC/{f=1;c++;print ""}  \
     f && /userName|serviceList|hostList|portNumber/ \
         {gsub(/ /,"",$1);  \
          gsub(/ /,"",$3);  \
          print $1 c "=" q $3 q} \
        /Children:/{f=0}' vars

userName1="test1"
serviceList1="ABC"
hostList1="159.220.108.3"
portNumber1="20001"

userName2="test2"
serviceList2="DEF"
hostList2="159.220.111.2"
portNumber2="20004"

它将为每个&#34;类增加计数器:ABC&#34;模式并设置一个标志。将格式化并打印所选条目,直到块的终端模式。这限制了两种模式之间的背景。

答案 2 :(得分:0)

假设bash 4.0或更新版本,根本不需要awk:

flush() {
  if (( ${#hostvars[@]} )); then
    for varname in userName serviceList hostList portNumber; do
      [[ ${hostvars[$varname]} ]] && {
        printf '%q=%q\n' "$varname" "${hostvars[$varname]}"
      }
    done
    printf '\n'
  fi
  hostvars=( )
}

class=
declare -A hostvars=( )
while read -r line; do
  [[ $line = *"Class: "* ]] && class=${line#*"Class: "} 
  [[ $class = ABC ]] || continue
  case $line in
    *:*:*)
      IFS=$': \t' read varName varType value <<<"$line"
      hostvars[$varName]=$value
      ;;
    *"Variables:"*)
      flush
      ;;
  esac
done
flush

值得注意的要点:

  • 完整的定义变量集合收集在hostvars关联数组中(其他语言可能称为&#34; map&#34;或&#34; hash&#34;),即使我们&# 39;只打印定义为感兴趣的四个名称。因此可以定义更有趣的逻辑,其组合多个变量来决定输出什么,&amp; c。
  • flush函数在循环外部定义,因此可以在多个位置使用 - 无论是在启动新块时(如检测到的,在此处,通过查看Variables:),以及在档案结尾。
  • 输出与您请求的内容不同,因为它仅在必要时包含引号 - 但该引用保证正确且足以使bash解析而无需安全漏洞,即使发出的字符串否则将包含安全性 - 相关内容。考虑正确处理serviceList包含$(rm -rf /*)'$(rm -rf /*)'的情况(存在重复以逃避单引号); printf %q使这很容易,而awk没有等价物。

答案 3 :(得分:0)

TXR中的解决方案:

@(collect)
@(skip)Class: ABC
Variables:
@  (gather)
 userName: String:@user
 serviceList: String: @servicelist
 hostList: String: @hostlist
 portNumber: Numeric: @port
@  (until)
 Children:
@  (end)
@(end)
@(deffilter shell-esc
   ("\"" "\\\"") ("$" "\\$") ("`" "\\'")
   ("\\" "\\\\"))
@(output :filter shell-esc)
@  (repeat :counter i)
userName@(succ i)="@user"
serviceList@(succ i)="@servicelist"
hostList@(succ i)="@hostlist"
portNumber@(succ i)="@port"
@  (end)
@(end)

执行命令

$ txr data.txr data
userName1="test1"
serviceList1="ABC"
hostList1="159.220.108.3"
portNumber1="20001"
userName2="test2"
serviceList2="DEF"
hostList2="159.220.111.2"
portNumber2="20004"

注1:如果数据可能包含目标语言中引号之间特殊的字符,则必须转义。 from tkinter import * Window = Tk() import make_entry make_entry.Create() Window.mainloop() 过滤器基于生成的变量赋值是shell语法的假设。它很容易被替换。

注2:该代码假定每个shell-esc都包含所有必需的变量。如果缺少某些内容,它将无法正常工作,有两种方法可以通过调整Class: ABC行来解决这个问题:

  • 失败:

    @(gather :vars (user servicelist hostlist port))
    

    含义:如果未收集这四个变量中的任何一个,则失败。结果是跳过了缺少变量的整个@(gather)部分。

  • 默认缺失:

    @(gather :vars (user (servicelist "ABC") hostlist port))
    

    含义:必须收集四个变量Class: ABCuserservicelisthostlist。但是,如果缺少port,则会获得默认值serviceList,并将其视为已找到。