免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 10718 | 回复: 21
打印 上一主题 下一主题

[文本处理] shell yaml 文本解析问题 [复制链接]

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-05-29 20:50 |只看该作者 |倒序浏览
10可用积分
本帖最后由 yjh777 于 2014-07-01 15:24 编辑

$ yamlStr='type: abc,  attr: "x,y,z",  name: kskdf sdf'

以逗号','分隔的键值对 key1: value1,  key2: "first part of value2,  second part of value2",  key3: value3
    其中value中可能有逗号, 请教怎么把这些键值对儿分开保存到一个数组里面?

试了IFS=,的方法,不好用:
$ eval IFS=, read -a aa <<< "$yamlStr"
$ for k in "${!aa[@]}"; do echo "$k-->${aa[$k]}"; done
0-->type: abc
1--> attr: "x
2-->y
3-->z"
4--> name: kskdf sdf

期望结果:
0-->type: abc
1--> attr: "x,y,z"
2--> name: kskdf sdf


请教大家有什么好方法?
---------------
发现最佳答案给错了,其实 jason680 和 damcool 给的答案更好;

基于jason680状态机方法的改进代码:
  1. #awk
  2. BEGIN {FS=""; P=0; S=0}
  3.         {
  4.                 for(n=1;n<=NF;n++) {
  5.                         if ($n==" " && $(n-1)==" " && P==0 && S==0)
  6.                                 continue
  7.                         if ($n=="," && P==0 && S==0) {
  8.                                 print gensub("^ ", "", 1, s); s=""
  9.                         } else {
  10.                                 s=s$n;
  11.                                 if(S==0 && $n=="\"" && $(n-1)!="\\")
  12.                                         P=(P+1)%2;
  13.                                 if(P==0 && $n=="'")
  14.                                         S=(S+1)%2
  15.                         }
  16.                 }
  17.         }
  18.         END {print gensub("^ ", "", 1, s)}'
复制代码

最佳答案

查看完整内容

这个意思吗?我想简单了?

论坛徽章:
36
摩羯座
日期:2013-09-23 16:37:312015年亚洲杯之沙特阿拉伯
日期:2015-04-14 09:10:172015亚冠之柏太阳神
日期:2015-06-25 08:48:212015亚冠之武里南联
日期:2015-07-28 09:01:082015亚冠之莱赫维亚
日期:2015-07-28 15:44:172015亚冠之柏斯波利斯
日期:2015-09-06 14:08:52白银圣斗士
日期:2015-11-25 17:06:2815-16赛季CBA联赛之吉林
日期:2015-12-09 16:59:072016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之辽宁
日期:2016-04-14 09:29:04luobin
日期:2016-06-17 17:46:3615-16赛季CBA联赛之天津
日期:2016-08-16 14:11:01
2 [报告]
发表于 2014-05-29 20:50 |只看该作者
  1. [root@dbserver ~]# echo 'type: abc,  attr: "x,y,z::\"$@#%^&",  name: kskdf sdf'|awk '{for(i=0;i++<split($0,b,", ");) print b[i]}'
  2. type: abc
  3. attr: "x,y,z::\"$@#%^&"
  4. name: kskdf sdf
复制代码
这个意思吗?我想简单了?

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
3 [报告]
发表于 2014-05-29 21:12 |只看该作者
本帖最后由 damcool 于 2014-05-29 21:25 编辑

  1. yamlStr='type: abc,  attr: "x,y,z",  name: kskdf sdf'
  2. eval IFS=, read -a aa <<< "$yamlStr"
  3. i=0;
  4. for k in "${!aa[@]}"; do
  5. if [[ "${aa[$k]}" =~ ":" ]] ; then
  6.     [ $i -ne 0 ] && echo "$i-->$ab"
  7.     i=$((i+1)) && ab="${aa[$k]}"
  8. else
  9.     ab="$ab, ${aa[$k]}"  
  10. fi
  11. done
  12. [ $i -ne 0 ] && echo "$i-->$ab"
复制代码
  1. echo 'type: abc,  attr: "x,y,z",  name: kskdf sdf'|awk '{n=split($0,a,",");for(i=1;i<=n;i++) if (match(a[i],":")) { if (j>0) print j"-->"k;j++;k=a[i]}else k=k""a[i]; if (j>0) print j"-->"k}'
复制代码

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
4 [报告]
发表于 2014-05-29 21:45 |只看该作者
回复 2# damcool

谢谢,这个只满足了一个特例; 怪我没说清楚: 这里不希望对  "" 里面的字符做解析

'type: abc,  attr: "x,y,z::\"$@#%^&",  name: kskdf sdf'


   

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
5 [报告]
发表于 2014-05-29 21:50 |只看该作者
那KeyName是固定的么?
yjh777 发表于 2014-05-29 21:45
回复 2# damcool

谢谢,这个只满足了一个特例; 怪我没说清楚: 这里不希望对  "" 里面的字符做解析

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
6 [报告]
发表于 2014-05-29 22:21 |只看该作者
回复 4# damcool

额,也不固定; 其实是想看bash有什么内置的功能可以设置,让它自动分割;可是试IFS没有按预想的来,,

如果实在不行,就得找yaml解释器或自己写解析代码了...

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
7 [报告]
发表于 2014-05-29 23:35 |只看该作者
yjh777 发表于 2014-05-29 22:21
回复 4# damcool

额,也不固定; 其实是想看bash有什么内置的功能可以设置,让它自动分割;可是试IFS没 ...


你举的第二个例子是特例,我相信如果Key Name不是有限的,Yaml也无法解析。

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
8 [报告]
发表于 2014-05-30 00:01 |只看该作者
本帖最后由 jason680 于 2014-05-30 00:02 编辑

回复 1# yjh777

$ echo $yamlStr | awk 'BEGIN{FS=""}{for(n=1;n<=NF;n++){if($n==","&&P==0){print s;s=""}else{s=s$n;if($n=="\""&&$(n-1)!="\\")P=(P+1)%2}}}END{print s}'
type: abc
attr: "x,y,z::\"$@#%^&"
name: kskdf sdf

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
9 [报告]
发表于 2014-05-30 00:08 |只看该作者
有点小挑战lol
  1. yamlStr='type: abc,  attr: "x,y,z::\"$@#%^&",  name: kskdf sdf'
  2. eval IFS=, read -a aa <<< "$yamlStr"
  3. i=0
  4. n=0
  5. key=""
  6. for k in "${!aa[@]}"; do
  7. if [[ "${aa[$k]}" =~ ":" ]] ; then
  8.     t="${key//\\\"/}";s=${#t};t="${t//\"/}";s=$((s-${#t}))
  9.     n=$(((n+s)%2))
  10.     if [ $n -eq 0 ]; then
  11.             [ $i -ne 0 ] && echo "$i-->$key"
  12.             i=$((i+1))
  13.             key="${aa[$k]}"
  14.     else
  15.             key="$key,${aa[$k]}"
  16.     fi
  17. else
  18.     key="$key,${aa[$k]}"
  19. fi
  20. done
  21. [ $i -ne 0 ] && echo "$i-->$key"

复制代码

论坛徽章:
2
白羊座
日期:2013-11-18 19:52:42辰龙
日期:2014-09-07 07:46:06
10 [报告]
发表于 2014-05-30 00:18 |只看该作者
  1. yamlStr='type: abc,  attr: "x","y","z",  name: kskdf sdf'
复制代码

jason680 发表于 2014-05-30 00:01
回复 1# yjh777

$ echo $yamlStr | awk 'BEGIN{FS=""}{for(n=1;n
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP