如何使用sed修复xml问题

时间:2015-07-13 18:41:17

标签: regex xml sed

我有一个带有以下(无效)结构的xml

<tag1>text1<tag2>text2</tag1><tag3>text3</tag3><tag1></tag2>text4</tag1>

我想用sed将其改成

<tag1>text1<tag2>text2<tag3>text3</tag3></tag2>text4</tag1>

即。如果遇到无效的xml子字符串为</tag1>...<tag1>

,我想删除tag1(并在封闭的<tag1></*下移动所有内容)

我尝试过使用sed但没有成功(下面有一个这样的尝试)

sed -e 's/<\/tag1>\(.*\)<tag1><\//\1<\//g'

它适用于上面的示例,但是如果我有两次出现相同的条件,则只删除第一个</tag1>和最后一个<tag1>,而不是执行两次替换

echo '<tag1>text1<tag2>text2</tag1><tag3>text3</tag3><tag1></tag2>text4</tag1><tag1>text5<tag4>text6</tag1><tag3>text7</tag3><tag1></tag4>text8</tag1>' | sed -e 's/<\/tag1>\(.*\)<tag1><\//\1<\//g'

输出

<tag1>text1<tag2>text2<tag3>text3</tag3><tag1></tag2>text4</tag1><tag1>text5<tag4>text6</tag1><tag3>text7</tag3></tag4>text8</tag1>

我认为sed只是扩展RE来覆盖最大的选择,但如果我不想让它做这样的事情该怎么办呢?

4 个答案:

答案 0 :(得分:1)

你想要非贪婪的匹配,但据我所知,sed并不支持它。你可以使用perl还是必须使用sed?

尝试:perl -p -e 's/<\/tag1>(.*?)<tag1>(\<\/.+?<\/tag1>)/\1\2/g'

我认为问题是正则表达式必须匹配到实际结束时,否则结束标记将成为下一场比赛的开始。

答案 1 :(得分:1)

sed 's|</tag1><tag3>|<tag3>|;s|</tag3><tag1>|</tag3>|' file.xml

输出:

<tag1>text1<tag2>text2<tag3>text3</tag3></tag2>text4</tag1>

答案 2 :(得分:1)

This might work for you (GNU sed):

sed -r 's/<tag1>/\n/g;s/<\/tag1>(<tag3>[^\n]*)\n/\1/g;s/\n/<tag1>/g' file

Reduce <tag1> to a unique character i.e \n then use the negated character class [^\n] to obtain non-greedy matching. Following the changes reverse the initial substitution.

答案 3 :(得分:0)

GNU sed

sed '\,<tag1></,{ s,</tag1>,,; s,<tag1>,,2; }' <<END
<tag1>text1<tag2>text2</tag1><tag3>text3</tag3><tag1></tag2>text4</tag1>  <!-- error case -->
<tag1><tag2 /></tag1><tag1><tag3 /></tag1>                                <!-- should not change -->
END
<tag1>text1<tag2>text2<tag3>text3</tag3></tag2>text4</tag1>  <!-- error case -->
<tag1><tag2 /></tag1><tag1><tag3 /></tag1>                                <!-- should not change -->

如果看到字符串<tag1></,则删除第一个</tag1>和第二个<tag1>