免费注册 查看新帖 |

Chinaunix

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

[文本处理] 从文本中取值求助 [复制链接]

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-01-27 22:13 |只看该作者 |倒序浏览
本帖最后由 bikkuri 于 2014-01-27 15:16 编辑

有这样一组数据:
data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
希望将每一个以空格分隔的字符串按以下方式赋值给三个变量:
$obj=":前面的字符串"
$code=":后面的部分但不包含[]部分"
$field="[和]中间的数字,如果没有[]部分,则为-1"
[]部分可能有,也可能没有

我知道可以用${}来分隔字符串,比如$obj可以通过obj=${str%%:*}来得到,
但是$code和$field可能要分隔两次,这样的话应该怎么写呢?
  1. data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. for str in $data; do
  3. obj=${str%%:*}
  4. code=${str##*:}
  5. printf "Object:%-6s Code:%-15s Field:%i\n" $obj $code $field
  6. done
复制代码
  1. Object:AAAA   Code:12K3456[1]      Field:0
  2. Object:BB     Code:2455F63         Field:0
  3. Object:CCC    Code:9452T045[3]     Field:0
  4. Object:D      Code:458J83[2]       Field:0
  5. Object:FF     Code:45245K39        Field:0
复制代码

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
2 [报告]
发表于 2014-01-27 23:39 |只看该作者
你给的结果跟你描述的不一样?
  1. awk '{for(i=0;i++<NF;){match($i,/([^:]+):([^[]+)\[?([^]]*)/,a);if(a[3]=="")a[3]=-1;printf "Object:%s\tCode:%s\tField:%s\n",a[1],a[2],a[3]}}' i
  2. Object:AAAA     Code:12K3456    Field:1
  3. Object:BB       Code:2455F63    Field:-1
  4. Object:CCC      Code:9452T045   Field:3
  5. Object:D        Code:458J83     Field:2
  6. Object:FF       Code:45245K39   Field:-1
复制代码

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
3 [报告]
发表于 2014-01-28 03:07 |只看该作者
谢谢您的答复。
我给出的程序和结果只是我还在修改的脚本,并没有实现我希望的输出。
您给出的输出是我希望得到的结果,但是busybox的awk好像不支持数组,所以您的程序在busybox下的输出是不正确的:
  1. root@jinx:/tmp# data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. root@jinx:/tmp# echo $data|awk '{for(i=0;i++<NF;){match($i,/([^:]+):([^[]+)\[?([^]]*)/,a);if(a[3]=="")a[3]=-1;printf "Object:%s\tCod
  3. e:%s\tField:%s\n",a[1],a[2],a[3]}}'
  4. Object: Code:   Field:-1
  5. Object: Code:   Field:-1
  6. Object: Code:   Field:-1
  7. Object: Code:   Field:-1
  8. Object: Code:   Field:-1
  9. root@jinx:/tmp#
复制代码
而且我还要在我的脚本中对$obj,$code及$field做进一步的处理,而不是直接print出来就完事,所以希望能在我的脚本上进行修改,只要让三个变量得到正确的赋值就好。谢谢!


回复 2# yestreenstars


   

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
4 [报告]
发表于 2014-01-28 03:55 |只看该作者
本帖最后由 bikkuri 于 2014-01-27 22:07 编辑

改了一下我的脚本,现在可以取到$obj和$code了,但是$field还是不能正确取值。
  1. data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. for str in $data; do
  3. obj=${str%:*}
  4. code=$(echo ${str#*:}|sed 's/\[.*\]//')
  5. field=$(echo ${str#*:}|sed 's/^.*\[\(.\)\]/\1/')
  6. printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
  7. done
复制代码
  1. Object:AAAA   Code:12K3456         Field:1
  2. Object:BB     Code:2455F63         Field:2455F63
  3. Object:CCC    Code:9452T045        Field:3
  4. Object:D      Code:458J83          Field:2
  5. Object:FF     Code:45245K39        Field:45245K39
复制代码
虽然可以用加一行[ $field == $code ] && field=-1这种耍无赖的方式得到我希望得到的输出,但是我想知道有没有不这样做就可以直接给$field正确赋值的方法?
  1. data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. for str in $data; do
  3. obj=${str%:*}
  4. code=$(echo ${str#*:}|sed 's/\[.*\]//')
  5. field=$(echo ${str#*:}|sed 's/^.*\[\(.\)\]/\1/')
  6. [ $field == $code ] && field=-1
  7. printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
  8. done
复制代码
  1. Object:AAAA   Code:12K3456         Field:1
  2. Object:BB     Code:2455F63         Field:-1
  3. Object:CCC    Code:9452T045        Field:3
  4. Object:D      Code:458J83          Field:2
  5. Object:FF     Code:45245K39        Field:-1
复制代码

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
5 [报告]
发表于 2014-01-28 09:36 |只看该作者
本帖最后由 yestreenstars 于 2014-01-28 09:36 编辑

回复 4# bikkuri

这样如何?
  1.         obj=${str%:*}
  2.         code=$(grep -oP '(?<=:)[^[]*' <<< $str)
  3.         field=$(grep -oP '(?<=\[)[^]]*' <<< $str)
  4.         field=${field:--1}
复制代码

论坛徽章:
0
6 [报告]
发表于 2014-01-28 09:37 |只看该作者
本帖最后由 jiejie455 于 2014-01-28 09:38 编辑
  1. bash-3.2$ for i in $data; do OLDIFS=$IFS; IFS="][: ";while read a b c;do if [[ -z $c ]]; then c=-1; fi;echo -e "Object:"$a"\tCode:"$b"\tField:"$c; done <<<$i;IFS=$OLDIFS; done
  2. Object:AAAA     Code:12K3456    Field:1
  3. Object:BB       Code:2455F63    Field:-1
  4. Object:CCC      Code:9452T045   Field:3
  5. Object:D        Code:458J83     Field:2
  6. Object:FF       Code:45245K39   Field:-1
复制代码

论坛徽章:
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
7 [报告]
发表于 2014-01-28 09:48 |只看该作者
回复 1# bikkuri


$ data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"

$ echo $data | perl -lane '{$_.=" ";while(m/(\w+):(\w+)(?:\[(\d+)\])?\s/g){printf"Object:%-6s Code:%-15s Fileld:%s\n",$1,$2,$3?$3:"-1"}}'

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

data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
for str in $data; do
  obj=`echo $str | awk -F'[]:[]+' '{print $1}'`
  code=`echo $str | awk -F'[]:[]+' '{print $2}'`
  field=`echo $str | awk -F'[]:[]+' '{print $3}'`
  printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code ${field:--1}
done
   

论坛徽章:
23
15-16赛季CBA联赛之吉林
日期:2017-12-21 16:39:27白羊座
日期:2014-10-27 11:14:37申猴
日期:2014-10-23 08:36:23金牛座
日期:2014-09-30 08:26:49午马
日期:2014-09-29 09:40:16射手座
日期:2014-11-25 08:56:112015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:0315-16赛季CBA联赛之山东
日期:2017-12-21 16:39:1915-16赛季CBA联赛之广东
日期:2016-01-19 13:33:372015亚冠之山东鲁能
日期:2015-10-13 09:39:062015亚冠之西悉尼流浪者
日期:2015-09-21 08:27:57
8 [报告]
发表于 2014-01-28 10:03 |只看该作者
回复 4# bikkuri


try:
  1. data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. for str in $data
  3. do
  4.         obj=$(echo $str | awk -F '[]:[]' '{print $1}')
  5.         code=$(echo $str | awk -F '[]:[]' '{print $2}')
  6.         field=$(echo $str | awk -F '[]:[]' '{print $3?$3:-1}')
  7.         printf "Object:%-6s Code:%-15s Field:%i\n" $obj $code $field
  8. done
复制代码
btw:
如果能说原始需求的话,结果肯定会更好。

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
9 [报告]
发表于 2014-01-28 22:46 |只看该作者
busybox也不支持<<<这种语法。。。
  1. root@unknown1:/tmp# data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
  2. root@unknown1:/tmp# for str in $data; do
  3. >         obj=${str%:*}
  4. >         code=$(grep -oP '(?<=:)[^[]*' <<< $str)
  5. -sh: syntax error: unexpected redirection
  6. root@unknown1:/tmp#         field=$(grep -oP '(?<=\[)[^]]*' <<< $str)
  7. -sh: syntax error: unexpected redirection
  8. root@unknown1:/tmp#         field=${field:--1}
  9. root@unknown1:/tmp# printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
  10. Object:FF     Code:45245K39        Field:-1
  11. root@unknown1:/tmp# done
  12. -sh: syntax error: unexpected "done"
  13. root@unknown1:/tmp#
复制代码
回复 5# yestreenstars


   

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
10 [报告]
发表于 2014-01-28 23:56 |只看该作者
谢谢7楼和8楼的回复,你们的输出都是正确的。
好像大家都更喜欢用awk,有用sed的朋友吗?

回复 8# ly5066113


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP