Chinaunix

标题: 正则表达式解析xml时遇到的问题 [打印本页]

作者: baicj    时间: 2008-01-08 14:14
标题: 正则表达式解析xml时遇到的问题
比如这样一个字符串:
<AAA>TEST</AAA><BBB>Test</BBB><AAA>test</AAA><BBB>TesT</BBB>

正则表达式应该怎么写才能提取出“TEST”?

用sed 's/<AAA>\(.*\)<\/AAA>.*/\1/'只能得到:TEST</AAA><BBB>Test</BBB><AAA>test

另外,为什么sed 's/<AAA>\(.*\)<\/AAA>/\1/'得到的结果是TEST</AAA><BBB>Test</BBB><AAA>test<BBB>TesT</BBB>
<BBB>TesT</BBB>是怎么来的?
作者: __lxmxn__    时间: 2008-01-08 14:27
  1. sed -r 's:<AAA>([^<>]*)</AAA>.*:\1:'
复制代码
  1. echo '<AAA>TEST</AAA><BBB>Test</BBB><AAA>test</AAA><BBB>TesT</BBB>'|perl -ne 'print $1 if m:<AAA>(.*?)</AAA>:'
复制代码


不知道sed的?有没有用...
作者: springwind426    时间: 2008-01-08 14:29

  1. sed 's/<AAA>\([^<]*\)<\/AAA>.*/\1/'
复制代码

作者: jinl    时间: 2008-01-08 14:40
原帖由 baicj 于 2008-1-8 14:14 发表
比如这样一个字符串:
TESTTesttestTesT

正则表达式应该怎么写才能提取出“TEST”?

用sed 's/\(.*\).*/\1/'只能得到:TESTTesttest

另外,为什么sed 's/\(.*\)/\1/'得到的结果是TESTTesttestTesT?
...


正则表达式匹配 按照最长匹配原则 ,也就是说 “/<aaa>.*<aaa>/匹配最长的 <aaa>囊括的字符串
对于你给的输入和正则表达式:

<AAA>TEST</AAA><BBB>Test</BBB><AAA>test</AAA><BBB>TesT</BBB>


用sed 's/<AAA>\(.*\)<\/AAA>.*/\1/'
\1代表最长的<AAA>之间的字符 : <AAA>TEST</AAA><BBB>Test</BBB><AAA>test</AAA>
所以只能得到:TEST</AAA><BBB>Test</BBB><AAA>test

另外,sed 's/<AAA>\(.*\)<\/AAA>/\1/'只替换了 <aaa>中间的部分,后面的 <bbb>部分没变化,自然
得到的结果是TEST</AAA><BBB>Test</BBB><AAA>test<BBB>TesT</BBB>?

[ 本帖最后由 jinl 于 2008-1-8 14:44 编辑 ]
作者: davistar    时间: 2008-01-08 14:50


  1. echo 'string' | gawk '{print gensub(/<AAA>([^<]*)<\/AAA>.*/,"\\1",1)}'
复制代码

作者: baicj    时间: 2008-01-08 14:53
明白了,谢谢三位!
看来perl脚本可以解决这个问题。

另外,如果是<AAA><BBB>TEST</BBB></AAA><AAA></AAA>这种情况呢,sed有没有可能取出第一个AAA的内容?
作者: ly5066113    时间: 2008-01-08 14:57
原帖由 baicj 于 2008-1-8 14:53 发表
明白了,谢谢三位!
看来perl脚本可以解决这个问题。

另外,如果是TEST这种情况呢,sed有没有可能取出第一个AAA的内容?


这不和你的第一个问题一样么?
作者: baicj    时间: 2008-01-08 14:59
不好意思,理解错了…三位的表达式都没有问题,谢谢
作者: baicj    时间: 2008-01-08 15:11
= =!
刚才测试了一下<AAA><BBB>TEST</BBB></AAA><AAA></AAA>,的确sed和awk的表达式不行,因为有[^<]*

是不是正则表达式的最大匹配原则让这种情况不能实现?除非用扩展的正则表达式,比如perl?
作者: jinl    时间: 2008-01-08 15:17
原帖由 baicj 于 2008-1-8 15:11 发表
= =!
刚才测试了一下TEST,的确sed和awk的表达式不行,因为有[^
a
awk应该可以实现阿,
awk -F "<[\]?AAA>" '{ print $1}'

[ 本帖最后由 jinl 于 2008-1-8 15:22 编辑 ]
作者: baicj    时间: 2008-01-08 15:30
原帖由 jinl 于 2008-1-8 15:17 发表
a
awk应该可以实现阿,
awk -F "" '{ print $1}'


不行,我把[\]换成[/]也匹配不到。

  1. #echo '<AAA><BBB>TEST</BBB></AAA><AAA></AAA>'| awk -F "<[\]?AAA>" '{ print $1}'
  2. awk: warning: escape sequence `\]' treated as plain `]'
  3. awk: fatal: Unmatched [ or [^: /<[]?AAA>/
  4. #
复制代码

作者: ly5066113    时间: 2008-01-08 15:36
echo '<AAA><BBB>TEST</BBB></AAA><AAA></AAA>' | awk -F '[><]+' '{print $4}'
作者: springwind426    时间: 2008-01-08 15:39

  1. echo '<AAA><BBB>TEST</BBB></AAA><AAA></AAA>' | sed 's/<\/AAA>/\n/;s/<AAA>\([^\n]*\).*/\1/'
复制代码


取出第一个<AAA>...</AAA>中的内容
作者: baicj    时间: 2008-01-08 15:43
标题: 回复 #12 ly5066113 的帖子
不知道可不可以不取文本,而把AAA下的内容"<BBB>TEST</BBB>"全部打出来?
作者: baicj    时间: 2008-01-08 15:50
原帖由 springwind426 于 2008-1-8 15:39 发表

echo 'TEST' | sed 's//\n/;s/\([^\n]*\).*/\1/'


取出第一个...中的内容


厉害,把结束符变成换行,好办法!
作者: jinl    时间: 2008-01-08 15:54
标题: 回复 #14 baicj 的帖子
echo "<AAA><BBB>TEST</BBB></AAA><AAA></AAA>"|awk -F "<[/]?AAA>" '{print $2}'
好像$1是空白,不过$2是需要的内容
作者: ggeneral    时间: 2013-02-23 21:07
本帖最后由 ggeneral 于 2013-02-23 21:09 编辑

  1. perl <<EOF
  2. use Data::Dumper;
  3. $_ = "<AAA>TEST</AAA><BBB>Test</BBB>";
  4. %res  = m{<(\w+)>(.*?)<\/\w+>}g;
  5. print Dumper \%res;
  6. EOF
复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2