bash—使用shell命令将特定的xml文档元素复制到另一个xml文档

kxxlusnw  于 2021-06-26  发布在  Kylin
关注(0)|答案(1)|浏览(523)

我正在通过shell脚本在aws emr上安装kylin。我有一个包含以下内容的xml文件,我需要从中将特定的文档元素复制到另一个xml文件中。这是在运行安装shell脚本时使用shell命令自动执行的手动步骤。
/etc/hbase/conf/hbase-site.xml文件

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
  <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
  </property>

  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>ip-nn-nn-nn-nn.ec2.internal</value>
  </property>

  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://ip-nn-nn-nn-nn.ec2.internal:xxxx/user/hbase</value>
  </property>

  <property>
    <name>dfs.support.append</name>
    <value>true</value>
  </property>

  <property>
    <name>hbase.rest.port</name>
    <value>xxxx</value>
  </property>
</configuration>

我需要将hbase.zookeeper.quorum属性从/etc/hbase/conf/hbase-site.xml复制到$kylin\u home/conf/kylin\u job\u conf.xml,如下所示:

<property>
  <name>hbase.zookeeper.quorum</name>
  <value>ip-nn-nn-nn-nn.ec2.internal</value>
</property>

注意:$kylin\u home/conf/kylin\u job\u conf.xml中已经包含一些其他数据。
需要将输出复制到目标文件。
目标文件“$kylin\u home/conf/kylin\u job\u conf.xml”如下所示:

<configuration>

    <property>
        <name>mapreduce.job.split.metainfo.maxsize</name>
        <value>-1</value>
        <description>The maximum permissible size of the split metainfo file.
            The JobTracker won't attempt to read split metainfo files bigger than
            the configured value. No limits if set to -1.
        </description>
    </property>

    <property>
        <name>mapreduce.map.output.compress</name>
        <value>true</value>
        <description>Compress map outputs</description>
    </property>

    <property>
        <name>mapreduce.output.fileoutputformat.compress</name>
        <value>true</value>
        <description>Compress the output of a MapReduce job</description>
    </property>

    <property>
        <name>mapreduce.output.fileoutputformat.compress.codec</name>
        <value>org.apache.hadoop.io.compress.SnappyCodec</value>
        <description>The compression codec to use for job outputs
        </description>
    </property>

    <property>
        <name>mapreduce.output.fileoutputformat.compress.type</name>
        <value>BLOCK</value>
        <description>The compression type to use for job outputs</description>
    </property>

    <property>
        <name>mapreduce.job.max.split.locations</name>
        <value>xxxx</value>
        <description>No description</description>
    </property>

    <property>
        <name>dfs.replication</name>
        <value>xxx</value>
        <description>Block replication</description>
    </property>

    <property>
        <name>mapreduce.task.timeout</name>
        <value>xxxx</value>
        <description>Set task timeout to 1 hour</description>
    </property>

</configuration>

预期产量:

<configuration>

    <property>
        <name>mapreduce.job.split.metainfo.maxsize</name>
        <value>-1</value>
        <description>The maximum permissible size of the split metainfo file.
            The JobTracker won't attempt to read split metainfo files bigger than
            the configured value. No limits if set to -1.
        </description>
    </property>

    <property>
        ---------
        ---------
        ---------
    </property>

    <property>
        ---------
        ---------
        ---------
    </property>

    <property>
        ---------
        ---------
        ---------
    </property>

    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>ip-nn-nn-nn-nn.ec2.internal</value>
    </property>

</configuration>

是否有任何shell命令可以从上述xml文件中提取特定的文档元素,并将其自动复制到另一个xml文件中。
我尝试了以下命令:

awk 'NR == FNR { if(FNR >= 30 && FNR <= 33) { patch = patch $0 ORS }; next } FNR == 88 { $0 = patch $0 } 1' /etc/hbase/conf/hbase-site.xml $KYLIN_HOME/conf/kylin_job_conf.xml > $KYLIN_HOME/conf/kylin_job_conf.xml

上面的命令对我无效。有人能帮我解决这个问题吗?

c9qzyr3d

c9qzyr3d1#

尝试用regex查询xml文件很少是个好主意。
总是喜欢使用xml解析器!
因此,您可以使用xmlstarlet完成给定的任务。它是一个程序,可以从输入(“input.xml”)中的一个命令中获取所需的数据:

xmlstarlet sel -t -c "/configuration/property[name='hbase.zookeeper.quorum']" input.xml

其输出为:

<property>
  <name>hbase.zookeeper.quorum</name>
  <value>ip-nn-nn-nn-nn.ec2.internal</value>
</property>

如果您的计算机上没有安装xmlstarlet,请执行以下操作:

sudo apt-get -y install xmlstarlet

命令行选项包括: sel :选择数据或查询xml文档(xpath等) -t :模板模式:解释模板的以下命令 -c :打印以下xpath表达式的副本
现在,在第二步中,将生成的xml复制到目标文件。这一点可以通过下面的答案中描述的方法实现:“如何使用xmlstarlet将xml文件附加到多个子节点?”
应用到您的示例中,以下命令行实现了您想要的功能:

xmlstarlet ed -a "/configuration/property[last()]" -t elem -n property \
-v "$(xmlstarlet sel -t -c "/configuration/property[name='hbase.zookeeper.quorum']/*" input.xml)" \
target.xml | xmlstarlet unesc | xmlstarlet fo > new_target.xml

结果 new_target.xml

<?xml version="1.0"?>
<configuration>
  <property>
    <name>mapreduce.job.split.metainfo.maxsize</name>
    <value>-1</value>
    <description>The maximum permissible size of the split metainfo file.
            The JobTracker won't attempt to read split metainfo files bigger than
            the configured value. No limits if set to -1.
        </description>
  </property>
  <property>
    <name>mapreduce.map.output.compress</name>
    <value>true</value>
    <description>Compress map outputs</description>
  </property>

  ...

  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>ip-nn-nn-nn-nn.ec2.internal</value>
  </property>
</configuration>

但是,这种方法有一个缺点:它取消了目标文件中所有实体的scape(使用 xmlstarlet unesc 命令),所以实体 &amp; 将转换为 & ... 这可能会破坏东西。
如果这是一个问题,请考虑使用带有完整xslt处理器和样式表的解决方案。

相关问题