Скопируйте определенный элемент документа XML в другой документ XML с помощью команд оболочки - PullRequest
0 голосов
/ 08 мая 2020

Я работаю над установкой Kylin на AWS EMR с помощью сценария оболочки. У меня есть файл xml с приведенным ниже содержимым, из которого мне нужно скопировать определенный элемент документа в другой файл xml. Это ручной шаг, который мне нужен для автоматизации с помощью команд оболочки при запуске сценария оболочки установки.

/ 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_HOME / conf / kylin_job_conf. xml, например:

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

Примечание: $ KYLIN_HOME / conf / kylin_job_conf. xml уже содержит некоторые другие данные внутри.

Необходимо скопировать вывод в целевой файл.

Целевой файл "$ KYLIN_HOME / conf / kylin_job_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>

Есть ли какая-либо команда оболочки, которая может извлечь конкретный элемент документа из файла 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

указанная выше команда не сработала для меня. Может ли кто-нибудь помочь мне, как решить эту проблему?

1 Ответ

2 голосов
/ 08 мая 2020

Попытка запросить файлы XML с помощью RegEx'ов редко бывает хорошей идеей.
Всегда предпочитайте использовать парсер 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>

Если на вашем компьютере не установлен , выполните

sudo apt-get -y install xmlstarlet

Параметры командной строки:

  • sel: Выберите данные или запрос XML документ (ы) (XPATH, et c)
  • -t: Режим шаблона: интерпретировать следующие команды для шаблонов
  • -c: распечатать копию следующего Выражение XPATH

Теперь на втором шаге скопируйте полученный XML в целевой файл. Это возможно с помощью метода, описанного в в этом SO-ответе: «Как использовать 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>

Однако у этого метода есть один недостаток: он отменяет экранирование всех сущностей в целевом файле (с xmlstarlet unesc command), поэтому такие объекты, как &amp;, будут преобразованы в & ... Это может сломать ситуацию.

Если это проблема, рассмотрите возможность использования решения с полным процессором XSLT и таблица стилей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...