Csv 使用awk解析字段中的字段

Csv 使用awk解析字段中的字段,csv,parsing,awk,Csv,Parsing,Awk,给定分隔符分隔的文件,例如things.file,包含 universe {planets;stars;people}, planet {countries; restaurants}, sky {clouds; planes} table {dishes}, chair {butts; more butts}, face {eyes; mouths} computers {memories; processors}, screens {good images; bad images; ugly

给定分隔符分隔的文件,例如things.file,包含

universe {planets;stars;people}, planet {countries; restaurants}, sky {clouds; planes}
table {dishes}, chair {butts; more butts}, face {eyes; mouths}
computers {memories; processors}, screens {good images; bad images; ugly images}, dogs {tails; fun }
我发现自己在做什么

$ awk -F"," '{print $2}' things.file | awk -F"{|}" '{print $2}' | awk -F";" '{print $1}'
countries
butts
good images
获取字段中的字段。是否有一种更干净的方法可以做到这一点,即不必三次调用awk?

对awk的调用更少,只需一次调用split函数,您可以按如下方式执行

awk -v FS=, '{ split($2, arr, /[{};]/);  print arr[2] }' file
$2上的split函数根据最后一个参数[{};]中提供的正则表达式对文本进行分隔,即,如果出现这些字符中的任何一个,则分割单词。拆分的单词存储在数组arr中,您可以从中检索所选单词

如果要删除前导空格和尾随空格,请添加替换函数以替换它,如下所示。在调用split之后和打印之前添加相同的内容

编辑:

你能试试下面的吗?我们可以在一个awk内完成


说明:将输入文件的所有行的字段分隔符设置为逗号。使用awk的“开箱即用”功能,为第2列提供正则表达式,从{直到第一次出现;然后打印起始点为变量RSTART till value of RLENGTH的子字符串,其中RSTART,RLENGTH变量将在三月函数中找到正则表达式后设置。

对字段可以包含的字符进行一系列假设,即它们看起来总是像您的示例,下面是如何解析数据,以便将来可以对其执行任何操作:

$ cat tst.awk
BEGIN { FS="[[:space:]]*,[[:space:]]*"; OFS="\t" }
{
    for (i=1; i<=NF; i++) {
        head = tail = $i
        sub(/[[:space:]]*{.*/,"",head)
        gsub(/.*{[[:space:]]*|[[:space:]]*}[[:space:]]*$/,"",tail)

        n = split(tail,subFlds,/[[:space:]]*;[[:space:]]*/)

        print "field:", $i
        print "head:", head
        print "tail:", tail
        for (j=1; j<=n; j++) {
            print "sub " j ":", subFlds[j]
        }
        print "\n------------\n"
    }
    print "############\n"
}

要更健壮地解析CSV,您的示例似乎只使用了{…},而常规CSV通常在awk中使用了{…},请参见

在一对{…}内或之间的任何地方是否可以有{、}、或换行?@EdMorton是的,这是一个很好的示例,但在我的情况下确实可以是{、}还有其他地方。我想知道被否决的人是否有意见。我被否决是因为几天后你仍然没有提供所有必要的信息,没有回答问题,也没有对任何答案提供反馈。好吧,很公平。我正在尽可能多地测试答案。我有时会有一些小变化,比如s我对@inian答案发表了评论,有时会交换;和。看起来不错,但速度有点慢。@myradio此答案中的脚本可能对您有效,也可能对您无效,但它们不会慢。@EdMorton事实上,这确实是超快的,并且给出了我所需要的。我没有发现我有错误,因为我在现场错过了我在一些文件中使用了d分隔符;并且进行了交换。这样做的诀窍是:awk-vfs=;{split$2,arr,/[{},]/;对于arr{printf%s中的I,arr[I]};printf\n}file.dsv'这只给了我第一个子字段,正如你所说的,{and;@myradio,我是从{直到第一次出现;它将提供它。这是正确的,但是我如何使用它来获取;{,}之间的所有子字段?@myradio,很高兴它帮助了您,您也可以选择此作为正确答案:
awk -F, '{gsub(/.*{|}/,"",$2);gsub(/; /,ORS,$2);print $2}'  Input_file
awk -F,  'match($2,/{[^;]*/){print substr($2,RSTART+1,RLENGTH-1)}' Input_file
$ cat tst.awk
BEGIN { FS="[[:space:]]*,[[:space:]]*"; OFS="\t" }
{
    for (i=1; i<=NF; i++) {
        head = tail = $i
        sub(/[[:space:]]*{.*/,"",head)
        gsub(/.*{[[:space:]]*|[[:space:]]*}[[:space:]]*$/,"",tail)

        n = split(tail,subFlds,/[[:space:]]*;[[:space:]]*/)

        print "field:", $i
        print "head:", head
        print "tail:", tail
        for (j=1; j<=n; j++) {
            print "sub " j ":", subFlds[j]
        }
        print "\n------------\n"
    }
    print "############\n"
}
$ awk -f tst.awk file
field:  universe {planets;stars;people}
head:   universe
tail:   planets;stars;people
sub 1:  planets
sub 2:  stars
sub 3:  people

------------

field:  planet {countries; restaurants}
head:   planet
tail:   countries; restaurants
sub 1:  countries
sub 2:  restaurants

------------

field:  sky {clouds; planes}
head:   sky
tail:   clouds; planes
sub 1:  clouds
sub 2:  planes

------------

############

field:  table {dishes}
head:   table
tail:   dishes
sub 1:  dishes

------------

field:  chair {butts; more butts}
head:   chair
tail:   butts; more butts
sub 1:  butts
sub 2:  more butts

------------

field:  face {eyes; mouths}
head:   face
tail:   eyes; mouths
sub 1:  eyes
sub 2:  mouths

------------

############

field:  computers {memories; processors}
head:   computers
tail:   memories; processors
sub 1:  memories
sub 2:  processors

------------

field:  screens {good images; bad images; ugly images}
head:   screens
tail:   good images; bad images; ugly images
sub 1:  good images
sub 2:  bad images
sub 3:  ugly images

------------

field:  dogs {tails; fun }
head:   dogs
tail:   tails; fun
sub 1:  tails
sub 2:  fun

------------

############