Chinaunix
标题:
从文本中取值求助
[打印本页]
作者:
bikkuri
时间:
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可能要分隔两次,这样的话应该怎么写呢?
data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
for str in $data; do
obj=${str%%:*}
code=${str##*:}
printf "Object:%-6s Code:%-15s Field:%i\n" $obj $code $field
done
复制代码
Object:AAAA Code:12K3456[1] Field:0
Object:BB Code:2455F63 Field:0
Object:CCC Code:9452T045[3] Field:0
Object:D Code:458J83[2] Field:0
Object:FF Code:45245K39 Field:0
复制代码
作者:
yestreenstars
时间:
2014-01-27 23:39
你给的结果跟你描述的不一样?
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
Object:AAAA Code:12K3456 Field:1
Object:BB Code:2455F63 Field:-1
Object:CCC Code:9452T045 Field:3
Object:D Code:458J83 Field:2
Object:FF Code:45245K39 Field:-1
复制代码
作者:
bikkuri
时间:
2014-01-28 03:07
谢谢您的答复。
我给出的程序和结果只是我还在修改的脚本,并没有实现我希望的输出。
您给出的输出是我希望得到的结果,但是busybox的awk好像不支持数组,所以您的程序在busybox下的输出是不正确的:
root@jinx:/tmp# data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
root@jinx:/tmp# echo $data|awk '{for(i=0;i++<NF;){match($i,/([^:]+):([^[]+)\[?([^]]*)/,a);if(a[3]=="")a[3]=-1;printf "Object:%s\tCod
e:%s\tField:%s\n",a[1],a[2],a[3]}}'
Object: Code: Field:-1
Object: Code: Field:-1
Object: Code: Field:-1
Object: Code: Field:-1
Object: Code: Field:-1
root@jinx:/tmp#
复制代码
而且我还要在我的脚本中对$obj,$code及$field做进一步的处理,而不是直接print出来就完事,所以希望能在我的脚本上进行修改,只要让三个变量得到正确的赋值就好。谢谢!
回复
2#
yestreenstars
作者:
bikkuri
时间:
2014-01-28 03:55
本帖最后由 bikkuri 于 2014-01-27 22:07 编辑
改了一下我的脚本,现在可以取到$obj和$code了,但是$field还是不能正确取值。
data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
for str in $data; do
obj=${str%:*}
code=$(echo ${str#*:}|sed 's/\[.*\]//')
field=$(echo ${str#*:}|sed 's/^.*\[\(.\)\]/\1/')
printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
done
复制代码
Object:AAAA Code:12K3456 Field:1
Object:BB Code:2455F63 Field:2455F63
Object:CCC Code:9452T045 Field:3
Object:D Code:458J83 Field:2
Object:FF Code:45245K39 Field:45245K39
复制代码
虽然可以用加一行[ $field == $code ] && field=-1这种耍无赖的方式得到我希望得到的输出,但是我想知道有没有不这样做就可以直接给$field正确赋值的方法?
data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
for str in $data; do
obj=${str%:*}
code=$(echo ${str#*:}|sed 's/\[.*\]//')
field=$(echo ${str#*:}|sed 's/^.*\[\(.\)\]/\1/')
[ $field == $code ] && field=-1
printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
done
复制代码
Object:AAAA Code:12K3456 Field:1
Object:BB Code:2455F63 Field:-1
Object:CCC Code:9452T045 Field:3
Object:D Code:458J83 Field:2
Object:FF Code:45245K39 Field:-1
复制代码
作者:
yestreenstars
时间:
2014-01-28 09:36
本帖最后由 yestreenstars 于 2014-01-28 09:36 编辑
回复
4#
bikkuri
这样如何?
obj=${str%:*}
code=$(grep -oP '(?<=:)[^[]*' <<< $str)
field=$(grep -oP '(?<=\[)[^]]*' <<< $str)
field=${field:--1}
复制代码
作者:
jiejie455
时间:
2014-01-28 09:37
本帖最后由 jiejie455 于 2014-01-28 09:38 编辑
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
Object:AAAA Code:12K3456 Field:1
Object:BB Code:2455F63 Field:-1
Object:CCC Code:9452T045 Field:3
Object:D Code:458J83 Field:2
Object:FF Code:45245K39 Field:-1
复制代码
作者:
jason680
时间:
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
作者:
ly5066113
时间:
2014-01-28 10:03
回复
4#
bikkuri
try:
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?$3:-1}')
printf "Object:%-6s Code:%-15s Field:%i\n" $obj $code $field
done
复制代码
btw:
如果能说原始需求的话,结果肯定会更好。
作者:
bikkuri
时间:
2014-01-28 22:46
busybox也不支持<<<这种语法。。。
root@unknown1:/tmp# data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
root@unknown1:/tmp# for str in $data; do
> obj=${str%:*}
> code=$(grep -oP '(?<=:)[^[]*' <<< $str)
-sh: syntax error: unexpected redirection
root@unknown1:/tmp# field=$(grep -oP '(?<=\[)[^]]*' <<< $str)
-sh: syntax error: unexpected redirection
root@unknown1:/tmp# field=${field:--1}
root@unknown1:/tmp# printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
Object:FF Code:45245K39 Field:-1
root@unknown1:/tmp# done
-sh: syntax error: unexpected "done"
root@unknown1:/tmp#
复制代码
回复
5#
yestreenstars
作者:
bikkuri
时间:
2014-01-28 23:56
谢谢7楼和8楼的回复,你们的输出都是正确的。
好像大家都更喜欢用awk,有用sed的朋友吗?
回复
8#
ly5066113
作者:
yestreenstars
时间:
2014-01-29 00:25
回复
10#
bikkuri
obj=${str%:*}
code=$(sed -r 's/.*:([^[]*).*/\1/' <<< $str)
field=$(sed -r 's/[^[]*\[?([^]]*).*/\1/' <<< $str)
field=${field:--1}
复制代码
作者:
bikkuri
时间:
2014-01-29 11:38
谢谢11楼的回复,由于busybox不支持<<<语法,您的代码在修改成如下后可以正确输出。
data="AAAA:12K3456[1] BB:2455F63 CCC:9452T045[3] D:458J83[2] FF:45245K39"
for str in $data; do
obj=${str%:*}
code=$(echo $str|sed -r 's/.*:([^[]*).*/\1/')
field=$(echo $str|sed -r 's/[^[]*\[?([^]]*).*/\1/')
field=${field:--1}
printf "Object:%-6s Code:%-15s Field:%s\n" $obj $code $field
done
复制代码
回复
11#
yestreenstars
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2