SED error - invalid reference \1 on `s' command's RHS extracting XML text

时间:2016-09-23 18:35:09

标签: linux sed

I have an XML file with multiple lines like below.

<sandbox>false</sandbox>
<serverUrl>https://salesforce.com/services/Soap/u/37.0/</serverUrl>
<sessionId>00D4100000087K9!AQMAQJElzjgvA01eaCo</sessionId>
<userId>00541000000JOzJAAW</userId>
<userInfo>

I am trying to use sed on Linux to get a value between the two sessionId tags.

sed -n '/<sessionId>.*$/{s/<sessionId>.*<\/sessionId>/\1/;p}' LoginResponse.xml

But it is throwing the below error. Any suggestions please...

sed: -e expression #1, char 50: invalid reference \1 on `s' command's RHS

2 个答案:

答案 0 :(得分:3)

正确的事

根本不要使用sed; XML不是常规语言,因此regular expressions are categorically not powerful enough to parse it correctly。您当前的代码无法将有关sessionId标记的注释与真实的sessionId标记区分开来;无法识别元素编码;无法处理您的代码中出现的意外属性;等

相反,请使用:

xmlstarlet sel -t -m '//sessionId' -v . -n < LoginResponse.xml

...或者,如果你没有XMLStarlet,你可以使用XSLTProc(在现代UNIX系统上几乎普遍可用的开箱即用)。如果您将以下内容另存为extract-session-id.xslt

<?xml version="1.0"?>
<!-- this was generated with:
  -- xmlstarlet sel -C -t -m '//sessionId' -v . -n
  -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
  <xsl:output omit-xml-declaration="yes" indent="no"/>
  <xsl:template match="/">
    <xsl:for-each select="//sessionId">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="."/>
      </xsl:call-template>
      <xsl:value-of select="'&#10;'"/>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="value-of-template">
    <xsl:param name="select"/>
    <xsl:value-of select="$select"/>
    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

...然后您可以运行xsltproc extract-session-id.xslt LoginResponse.xml来获取输出。

sed事物

也就是说,关于你的sed错误:你需要通过-r来启用ERE语法:

# requires GNU sed for -r
sed -r -n -e '/<sessionId>.*$/{s/<sessionId>(.*)<\/sessionId>/\1/;p}'

或者,使用MacOS BSD sed,还需要进行一些其他调整:

# -E, not -r, on MacOS BSD sed; semicolon between "p", "}" needed.
sed -E -n '/<sessionId>.*$/ { s/<sessionId>(.*)<\/sessionId>/\1/; p; }'

如果你的会话ID曾经包含元素后面的字符,那么这会很糟糕 - & s看起来像&amp;,依此类推;因此,使用适当的XML解析器是更安全的选择。 (同样,如果内容曾经发生变化<sessionid type="foo">...</sessionid>,或者发生任何其他变化的情况。)

答案 1 :(得分:0)

对于工作的参考,你必须告诉说使用圆括号引用什么,你没有。

试试此链接: - http://www.grymoire.com/Unix/Sed.html#uh-4