【问题标题】:extract data between tags <t> </t>提取标签之间的数据 <t> </t>
【发布时间】:2021-07-18 13:22:15
【问题描述】:

我有如下数据 如何打印两个标签之间的数据 我希望数据是命令分隔的 csv 格式

我的方法是将数据转换为水平格式,然后在每 4 列后剪切并转换为垂直格式

xml文件中的数据

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
-
<sst uniqueCount="12" count="12"
    xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
-
    <si>
        <t>"NAME"</t>
    </si>
-
    <si>
        <t>"Vikas"</t>
    </si>
-
    <si>
        <t>"Vijay"</t>
    </si>
-
    <si>
        <t>"Vilas"</t>
    </si>
-
    <si>
        <t>"AGE"</t>
    </si>
-
    <si>
        <t>"24"</t>
    </si>
-
    <si>
        <t>"34"</t>
    </si>
-
    <si>
        <t>"35"</t>
    </si>
-
    <si>
        <t>"COURSE"</t>
    </si>
-
    <si>
        <t>"MCA"</t>
    </si>
-
    <si>
        <t>"MMS"</t>
    </si>
-
    <si>
        <t>"MBA"</t>
    </si>
</sst>
      

我试过下面这个命令不起作用..

awk '/<t/{flag=1;next}/<t/{flag=0}flag' abc.xml

即使在下面的命令中尝试过,它也提供数据,但在单行中

awk -F'(</*t>|</*t>)' 'NF>1{for(i=2;i<NF; i=i+2) printf("%s%s", $i, (i+1==NF)?ORS:OFS)}' OFS=',' demo.xml

我想要下面的数据作为输出

NAME,AGE,Course
Vikas,"25",MCA
Prabhash,"34",MBA
Arjun,"21",MMS

【问题讨论】:

  • 能否请您以文本形式在您的问题中发布您的数据样本,以便我们在发布之前测试我们的代码,谢谢。
  • @RavinderSingh13 确定 2 分钟
  • @RavinderSingh13 现在试试我已经粘贴了实际的 xml 代码
  • 感谢编辑。你的&lt;t&gt;AGE&lt;/t&gt;不应该出现在你所有的行之前,比如&lt;t&gt;"25"&lt;/t&gt;吗?您的系统中还安装了 xmlstarlet 之类的工具吗?请让我知道这两个问题,谢谢。
  • @RavinderSingh13 检查 2 分钟

标签: shell unix


【解决方案1】:

只有您显示的示例,请您尝试以下操作。

awk -v OFS="," '
!NF || /^-$/{ next }
/<t>"COURSE"<\/t>/{
  foundAge=foundName=""
  foundCourse=1
  count=0
}
/<t>"AGE"<\/t>/{
  foundAge=1
  foundName=""
  count=0
}
/<t>"NAME"<\/t>/{
  foundName=1
  count=0
}
foundAge && match($0,/>[^<]*/){
  age[++count]=substr($0,RSTART+1,RLENGTH-1)
}
foundName && match($0,/>[^<]*/){
  name[++count]=substr($0,RSTART+1,RLENGTH-1)
}
foundCourse && match($0,/>[^<]*/){
  course[++count]=substr($0,RSTART+1,RLENGTH-1)
}
END{
  for(k=1;k<=count;k++){
    if(name[k]){
      print name[k],age[k],course[k]
    }
  }
}
'  Input_file

说明:为上述添加详细说明。

awk -v OFS="," '                                 ##Starting awk program from here.
!NF || /^-$/{ next }                             ##if line is empty or starts with - then skip that line.
/<t>"COURSE"<\/t>/{                              ##Checking if line has <t>"COURSE"</t> then do following.
  foundAge=foundName=""                          ##Nullifying foundAge and foundName here.
  foundCourse=1                                  ##Setting foundCourse to 1 here.
  count=0                                        ##Setting count to 0 here.
}
/<t>"AGE"<\/t>/{                                 ##Checking if line has <t>"AGE"</t> then do following.
  foundAge=1                                     ##Setting foundAge to 1 here.
  foundName=foundCourse=""                       ##Nullifying foundName and foundCourse here.
  count=0                                        ##Setting count to 0 here.
}
/<t>"NAME"<\/t>/{                                ##Checking if line has <t>"NAME"</t> then do following.
  foundName=1                                    ##Setting foundName to 1 here.
  count=0                                        ##Setting count to 0 here.
}
foundAge && match($0,/>[^<]*/){                  ##Checking if foundAge is set and using match function to get values from > to till < here.
  age[++count]=substr($0,RSTART+1,RLENGTH-1)     ##Creating age with index of count and having matched regex value here.
}
foundName && match($0,/>[^<]*/){                 ##Checking if foundName is set and using match function to get values from > to till < here.
  name[++count]=substr($0,RSTART+1,RLENGTH-1)    ##Creating name with index of count and having matched regex value here.
}
foundCourse && match($0,/>[^<]*/){               ##Checking if foundCourse is set and using match function to get values from > to till < here.
  course[++count]=substr($0,RSTART+1,RLENGTH-1)  ##Creating course with index of count and having matched regex value here.
}
END{                                             ##Starting END block of this awk program from here.
  for(k=1;k<=count;k++){                         ##Traversing through all elements of name here.
    if(name[k]){
      print name[k],age[k],course[k]             ##Printing respective array values here.
    }
  }
}
'  Input_file                                    ##Mentioning Input_file name here.


编辑:根据 OP 的评论,如果一行需要所有值,请尝试以下操作:

awk -v OFS="," '
!NF || /^-$/{ next }
/<t>"COURSE"<\/t>/{
  foundAge=foundName=""
  foundCourse=1
  count=0
}
/<t>"AGE"<\/t>/{
  foundAge=1
  foundName=""
  count=0
}
/<t>"NAME"<\/t>/{
  foundName=1
  count=0
}
foundAge && match($0,/>[^<]*/){
  age[++count]=substr($0,RSTART+1,RLENGTH-1)
}
foundName && match($0,/>[^<]*/){
  name[++count]=substr($0,RSTART+1,RLENGTH-1)
}
foundCourse && match($0,/>[^<]*/){
  course[++count]=substr($0,RSTART+1,RLENGTH-1)
}
END{
  for(k=1;k<=count;k++){
     if(name[k]){
     nameVal=(nameVal?nameVal OFS:"")name[k]
     ageVal=(ageVal?ageVal OFS:"")age[k]
     courseVal=(courseVal?courseVal OFS:"")course[k]
     }
  }
  print nameVal,ageVal,courseVal
}
'  Input_file

【讨论】:

  • 好兄弟,你能在每一行添加一些描述你的代码实际上做了什么
  • @codeholic24,是的,正在进行的工作将在一分钟左右完成。
  • @codeholic24,嘿,我之前也要求检查的另一件事,你不能在你的盒子里安装任何软件,比如 xmlstarlet 等?请确认一次(说明在 porgress 中),干杯。
  • @RavinderSingh13 你能把来自这个命令的数据转换成上面的输出吗:awk -F'(&lt;/*t&gt;|&lt;/*t&gt;)' 'NF&gt;1{for(i=2;i&lt;NF; i=i+2) printf("%s%s", $i, (i+1==NF)?ORS:OFS)}' OFS=',' demo.xml
  • 是的,我正在尝试添加新问题,只需检查几分钟
猜你喜欢
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
相关资源
最近更新 更多