Переменные внутри heredoc с несколькими файлами

Переключение вещей вgcc -o $(out=$(mktemp); echo $out):

out=$(mktemp); echo "$out"; gcc -o "$out" hello.c

... что также удобно оставляет путь в переменной для последующего использования. (По-видимому, вы не хотите просто видеть путь в выводе, чтобы полюбоваться красотой генерации случайных имен mktemp, верно? Вы хотите, чтобы этот путь использовался в другом месте.)

1
31.10.2020, 01:45
3 ответа

Вы можете использовать envsubstздесь:

bar=$(baz=$(cat baz.xml) envsubst '$baz' < bar.xml) envsubst '$bar' << 'EOF'
<foo>
  $bar
</foo>
EOF

Это обеспечит расширение только $bar/ ${bar}/ $baz/ ${baz}, а не других расширений ($(cmd), `cmd`, $((arith)), ${x#y}... )или другие переменные, как в:

bar=$(cat bar.xml)
baz=$(cat baz.xml)
eval "cat << EOF
<foo>
  $bar
</foo>
EOF"

подход.

1
18.03.2021, 22:53

Я нашел это решение, не знаю, есть ли что-то лучше:

sed -i '/<bar>/r baz.xml' bar.xml

а затем вот документ:

bar=$(cat bar.xml)

cat << EOF > out.xml
<foo>
  $bar
</foo>
EOF

который выводит желаемый результат:

<foo>
  <bar>
    <baz>baz</baz>
  </bar>
</foo>
0
18.03.2021, 22:53

Идиоматическим способом объединения документов XML является использование XSLT. Во-первых, некоторые настройки:

$ cd "$(mktemp --directory)"
$ echo '<foo/>' >./foo.xml
$ echo '<bar/>' >./bar.xml
$ echo '<baz/>' >./baz.xml

Затем мы создаем файл XSLT, который будет вставлять содержимое одного файла в элемент исходного файла, копируя остальную часть файла, как -:

$ cat >./insert.xslt <<'EOF'
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
>     <xsl:template match="@* | node()">
>         <xsl:copy>
>             <xsl:apply-templates select="@* | node()"/>
>             <xsl:if test="name() = $element">
>                 <xsl:copy-of select="document($file)"/>
>             </xsl:if>
>         </xsl:copy>
>     </xsl:template>
> </xsl:stylesheet>
> EOF

Теперь мы можем вставить произвольный файл в другой:

$ xsltproc --output./bar-insert.xml --stringparam file./baz.xml --stringparam element bar./insert.xslt./bar.xml
$ cat./bar-insert.xml
<?xml version="1.0"?>
<bar><baz/></bar>

Повторим, чтобы создать окончательный файл:

$ xsltproc --output./foo-insert.xml --stringparam file./bar-insert.xml --stringparam element foo./insert.xslt./foo.xml
$ cat./foo-insert.xml
<?xml version="1.0"?>
<foo><bar><baz/></bar></foo>

Преимущество этого заключается в том, что он будет работать с любыми файлами XML, независимо от того, имеют ли они отступы, свернуты ли пустые элементы и так далее.


Он даже вставит файл более одного раза, если на него ссылаются более одного раза. Например, для данного people.xml:

<people>
    <managers>
        <name>Jane Doe</name>
        <reports>
            <insert/>
        </reports>
    </managers>
    <interns>
        <insert/>
    </interns>
</people>

и вставка.xml:

<name>Abe Lincoln</name>

Теперь мы можем тривиально разместить файл insert.xml в обоих местах:

$ xsltproc --stringparam file./insert.xml --stringparam element insert./insert.xslt./people.xml 
<?xml version="1.0"?>
<people>
    <managers>
        <name>Jane Doe</name>
        <reports>
            <insert><name>Abe Lincoln</name></insert>
        </reports>
    </managers>
    <interns>
        <insert><name>Abe Lincoln</name></insert>
    </interns>
</people>
2
18.03.2021, 22:53

Теги

Похожие вопросы