如何使用shell脚本提取xml属性?

时间:2008-10-09 22:58:26

标签: xml bash shell

我已经使用grep从源文档中提取了标记,但现在我似乎无法弄清楚如何从字符串中轻松提取属性。另外,我想避免使用标准安装中通常不会出现的任何程序。

$tag='<img src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg" title="Don't we all." alt="Barrel - Part 1" />'  

我需要最终得到以下变量

$src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg"
$title="Don't we all."
$alt="Barrel - Part 1"

4 个答案:

答案 0 :(得分:4)

您可以使用xmlstarlet。然后,您甚至不必自己提取元素:

$ echo $tag|xmlstarlet sel -t --value-of '//img/@src'
http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg

你甚至可以把它变成一个功能

$ get_attribute() {
  echo $1 | xmlstarlet sel -t -o "&quot;" -v $2 -o "&quot;"
  }
$ src=get_attribute $tag '//img/@src'

如果您不想多次重新分析文档,也可以执行以下操作:

$ get_values() {
   eval file=\${$#}
   eval $#=    
   cmd="xmlstarlet sel "
   for arg in $@
   do
      if [ -n $arg ]
      then
        var=${arg%%\=*}
        expr=${arg#*=}
        cmd+=" -t -o \"$var=&quot;\" -v $expr -o \"&quot;\" -n"
      fi
   done
   eval $cmd $file
  }
$ eval $(get_values src='//img/@src' title='//img/@title' your_file.xml)
$ echo $src
http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg
$ echo $title
Don't we all.

我确信有更好的方法可以删除shell函数的最后一个参数,但我不知道。

答案 1 :(得分:1)

我选择了dacracot建议使用sed,虽然如果他给了我一些示例代码我会更喜欢

src=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\1/'`    
title=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\2/'`  
alt=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\3/'`

答案 2 :(得分:0)

如果xmlstarlet在标准安装中可用且src-title-alt的顺序没有改变,您也可以使用以下代码:

tag='<img src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg" title="Don'"'"'t we all." alt="Barrel - Part 1" />'
xmlstarlet sel -T -t -m "/img" -m "@*" -v '.' -n <<< "$tag"
IFS=$'\n'
array=( $(xmlstarlet sel -T -t -m "/img" -m "@*" -v '.' -n <<< "$tag") )
src="${array[0]}"
title="${array[1]}"
alt="${array[2]}"

printf "%s\n" "src: $src" "title: $title" "alt: $alt"

答案 3 :(得分:0)

由于这再次冒出来,现在我的Xidel有2个功能使这个任务变得微不足道:

  • xml上的模式匹配

  • 将所有匹配的变量导出到shell

所以它变成了一行:

eval $(xidel "$tag" -e '<img src="{$src}" title="{$title}" alt="{$alt}"/>' --output-format bash)