【问题标题】:Using AWK to parse fields with commas使用 AWK 解析带逗号的字段
【发布时间】:2015-06-16 15:54:36
【问题描述】:

已编辑 - TLDR:使用 awk 解析包含逗号的字段。

# 原始配置文件 - confile1
$ cat confile1
list=(
app1,"HOSTNAME - port - application name - alert1",99.0,99.0
app2,"HOSTNAME - port - application name - alert1",99.0,99.0
app3,"HOSTNAME - port - service name - alert2",99.0,99.0
web1,"URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1",99.0,99.0
)
# 原始脚本 - test1
$ cat test1
#!/bin/bash

IFS="$(printf '\n\t')"

function parse
{
for item in ${list[*]}
do
  group=$(echo $item | awk -F, '{print $1}')
  monitor=$(echo $item | awk -F, '{print $2}')
  grp_sla=$(echo $item | awk -F, '{print $3}')
  mon_sla=$(echo $item | awk -F, '{print $4}')
  echo $group
  echo $monitor
  echo $grp_sla
  echo $mon_sla
done
}

. confile1
parse

请注意,conffile1 的最后一行被删除了,因为它在第二个字段中有一个逗号

  $ ./test1
    app1
    HOSTNAME - port - application name - alert1
    99.0
    99.0
    app2
    HOSTNAME - port - application name - alert1
    99.0
    99.0
    app3
    HOSTNAME - port - service name - alert2
    99.0
    99.0
    web1
    URL - HOSTNAMES(01
    02) - http://someurl.com/ - alert1
    99.0

【问题讨论】:

  • 你的问题太长了,大多数人都不愿意花时间阅读和理解它,以便他们可以帮助你。摆脱所有绒毛(my office uses HP Sitescope.. = 不相关的细节)并将其剥离为基础知识 - 简要描述、示例输入、预期输出以及您尝试过的内容。正确的解决方案除了调用awk 外不涉及任何shell 命令。 UNIX shell 是一个环境,从中可以使用一种语言调用工具来对这些调用进行排序,而用于操作文本的 UNIX 工具是 awk,因此无论您尝试做什么,都只是一个 awk 脚本

标签: regex bash shell awk


【解决方案1】:

我不愿意回答你的整个问题(抱歉,恕我直言,太多无关信息太长了),但看起来你正试图从顶部的“confile1”中提取各个字段你的问题,所以也许这就是你需要的所有提示:

$ cat tst.awk
BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" }
NF>1 {
    print "\nRecord", ++nr":", $0
    for (i=1; i<=NF; i++) {
        print "   Field", i":", $i
    }
}

$ awk -f tst.awk confile1

Record 1: app1,"HOSTNAME - port - application name - alert1",99.0,99.0
   Field 1: app1
   Field 2: "HOSTNAME - port - application name - alert1"
   Field 3: 99.0
   Field 4: 99.0

Record 2: app2,"HOSTNAME - port - application name - alert1",99.0,99.0
   Field 1: app2
   Field 2: "HOSTNAME - port - application name - alert1"
   Field 3: 99.0
   Field 4: 99.0

Record 3: app3,"HOSTNAME - port - service name - alert2",99.0,99.0
   Field 1: app3
   Field 2: "HOSTNAME - port - service name - alert2"
   Field 3: 99.0
   Field 4: 99.0

Record 4: web1,"URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1",99.0,99.0
   Field 1: web1
   Field 2: "URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1"
   Field 3: 99.0
   Field 4: 99.0

以上使用 GNU awk 进行 FPAT(请参阅 http://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content)。

特别是由于您是自学,我强烈建议您阅读 Arnold Robbins 的《Effective Awk Programming, 4th Edition》和 Chris Johnson 的《Shell Scripting Recipes》,因为在 UNIX 中走错路非常容易,因为所有这些解决任何一个问题的可能方法。

【讨论】:

  • 我认为我的帖子可能太长了,但这是我的第一个问题,我想提供尽可能多的信息。您通过您提供的链接让我走上了正确的道路。谢谢!
【解决方案2】:

针对您的特定设置的另一种解决方案是使用 NF 来控制字段。在这里,我设置了 OFS 以使其更显眼。

$ awk -F, 'BEGIN{OFS=" <-> "} NF==4{print $1, $2, $3, $4 } NF==5{print $1, $2","$3, $4, $5}' data.csv

app1 <-> "HOSTNAME - port - application name - alert1" <-> 99.0 <-> 99.0
app2 <-> "HOSTNAME - port - application name - alert1" <-> 99.0 <-> 99.0
app3 <-> "HOSTNAME - port - service name - alert2" <-> 99.0 <-> 99.0
web1 <-> "URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1" <-> 99.0 <-> 99.0

【讨论】:

    【解决方案3】:

    Ed Morton 提供了我需要的确切信息。我已经在我的主脚本上对此进行了测试,并且可以完美解析!这是测试代码的工作:

    $ awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $0}' confile4
    app1,"HOSTNAME - port - application name - alert1",99.0,99.0
    app2,"HOSTNAME - port - application name - alert1",99.0,99.0
    app3,"HOSTNAME - port - service name - alert2",99.0,99.0
    web1,"URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1",99.0,99.0
    
    
    $ cat test10
    #!/bin/bash
    
    IFS="$(printf '\n\t')"
    
    function parse
    {
    for item in $(awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $0}' confile4)
    do
      group=$(echo $item | awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $1}')
      monitor=$(echo $item | awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $2}')
      grp_sla=$(echo $item | awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $3}')
      mon_sla=$(echo $item | awk 'BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } {print $4}')
      echo $group
      echo $monitor
      echo $grp_sla
      echo $mon_sla
    done
    }
    
    parse
    
    $ ./test10
    app1
    "HOSTNAME - port - application name - alert1"
    99.0
    99.0
    app2
    "HOSTNAME - port - application name - alert1"
    99.0
    99.0
    app3
    "HOSTNAME - port - service name - alert2"
    99.0
    99.0
    web1
    "URL - HOSTNAMES(01,02) - http://someurl.com/ - alert1"
    99.0
    99.0
    

    【讨论】:

    • 这绝对是做你想做的任何事情的错误方法。您对 shell 的用途以及如何使用它感到困惑 - 您在脚本中所做的事情,虽然它可能会产生您想要的效果,但在好的软件的每个可能方面(例如性能,健壮性、简洁性等)。
    猜你喜欢
    • 1970-01-01
    • 2011-05-11
    • 2011-05-20
    • 2020-01-21
    • 2014-10-22
    • 2013-01-16
    • 2017-09-14
    • 1970-01-01
    • 2013-01-28
    相关资源
    最近更新 更多