99 votos

Limpia manera de escribir complejo multi-línea de cadena a una variable

Necesito escribir algunos complejo de xml a una variable dentro de un script de bash. El xml debe ser legible dentro de la secuencia de comandos bash como este es donde el fragmento de xml se vivir, no se leen de otro archivo o fuente.

Así que mi pregunta es si tengo una cadena larga de la que quiero ser legible por humanos dentro de mi script de bash ¿cuál es la mejor manera de ir sobre ella?

Idealmente quiero:

  • para no tener que escapar de los personajes
  • tienen que romper a través de múltiples líneas de lo que es legible por humanos
  • mantener la sangría

Se puede hacer esto con EF o algo, alguien podría darme un ejemplo?

por ejemplo,

String = <<EOF
 <?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

129voto

jason saldo Puntos 5036

Esto pondrá su texto en la variable sin necesidad de escapar de la cita. Que también se encargará de la desequilibrada comillas (comillas). Poner comillas alrededor de la sentinal (EF) impide que el texto sometidos a la expansión de parámetros. El -d'' de las causas que leer varias líneas (ignorar el carácter de nueva línea). read es un Bash incorporado por lo tanto no requiere llamar a un comando externo como cat.

read -d '' String <<"EOF"
<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

29voto

Crippeoblade Puntos 1301

Ha sido casi allí. Ya sea que usted use el gato para el montaje de su cadena o citar a toda la cadena (en cuyo caso tendría que escapar las comillas dentro de su cadena):

#!/bin/sh
VAR1=$(cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
)

VAR2="<?xml version=\"1.0\" encoding='UTF-8'?>
<painting>
  <img src=\"madonna.jpg\" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's \"Foligno\" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>"

echo "${VAR1}"
echo "${VAR2}"

11voto

schweiz Puntos 59
#!/bin/sh

VAR1=`cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
`
echo "VAR1: ${VAR1}"

Esto debería funcionar bien dentro del entorno de la shell Bourne

4voto

F. Hauri Puntos 663

Sin embargo, otra forma de hacer lo mismo...

Me gusta usar variables y especiales de la <<- que dejan de tabulación en el comienzo de cada una de las líneas para permitir la secuencia de comandos de sangría:

#!/bin/bash

mapfile Pattern <<-eof
        <?xml version="1.0" encoding='UTF-8'?>
        <painting>
          <img src="%s" alt='%s'/>
          <caption>%s, painted in
          <date>%s</date>-<date>%s</date>.</caption>
        </painting>
        eof

while IFS=";" read file alt caption start end ;do
    printf "${Pattern[*]}" "$file" "$alt" "$caption" "$start" "$end"
  done <<-eof
        madonna.jpg;Foligno Madonna, by Raphael;This is Raphael's "Foligno" Madonna;1511;1512
        eof

advertencia: no hay ningún espacio en blanco antes de eof , pero sólo tabulación.

<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>

Algunas explicaciones:

  • mapfile leer entero aquí el documento en una matriz.
  • la syntaxe "${Pattern[*]}" hacer elenco de esta matriz en una cadena.
  • Yo uso IFS=";" porque no hay ninguna ; requerida en las cadenas de
  • La syntaxe while IFS=";" read file ... prevenir IFS a ser modificado por el resto de la secuencia de comandos. En este, sólo read hace uso de la modificadas IFS.
  • ningún tenedor.

2voto

Chris Johnson Puntos 263

Hay demasiados casos de esquina en muchas de las otras respuestas.

Para estar absolutamente seguro de que no hay problemas con los espacios, tabulaciones, IFS, etc., un mejor enfoque es utilizar el "heredoc" construir, pero codificar el contenido de la heredoc usando uuencode como se explica aquí:

http://stackoverflow.com/questions/6896025/#11379627.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: