Soru Bir değişkene karmaşık çok satırlı dize yazmak için temiz bir yol


Bir bash komut dosyasında bir değişkene biraz karmaşık xml yazmam gerek. Xml parçasının yaşayacağı yer olan betik betiğinin içinde okunabilmesi için xml'nin başka bir dosyadan veya kaynaktan okunmaması gerekir.

Bu yüzden benim soru şu ki, bash betimlemde insan tarafından okunabilir olmak istediğim uzun bir dizim varsa bununla ilgili en iyi yol nedir?

İdeal olarak istiyorum:

  • karakterlerden kaçmak zorunda değil
  • insanı okunabilir hale getirmek için birden fazla hatta kırılsın mı
  • girinti tutmak

Bu EOF ya da bir şey ile yapılabilir mi, bana bir örnek verebilir misiniz?

Örneğin.

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

94
2017-10-08 10:54


Menşei


Bahse girerim ki, bu verileri tekrar bir akıma dökeceksin. İşleri daha karmaşık hale getirip akışları kullanabildiğinizde neden bir değişkende saklayın? - Zenexer
bunu da gör: Ekstra alana sahip çok satırlı dize (korunmuş girinti) - Yibo Yang


Cevaplar:


Bu, metninizi, tekliflerden kaçmak zorunda kalmadan değişkeninize dahil edecektir. Dengesiz teklifleri de ele alacak (kesme işaretleri, yani. '). Gönderenin (EOF) etrafına tırnak koymak, metnin parametre genişlemesine geçmesini engeller. -d'' Birden çok satır okumasını sağlar (yeni satırları yok say). read bir Bash yerleşiktir, bu yüzden harici bir komut çağırmak gerektirmez cat.

IFS='' read -r -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

123
2017-10-08 12:37



Kaçınılması gereken +1 cat. - James Sneeringer
cat harici bir komuttur. Bunu kullanmamak, bunu kaydeder. Artı, bazı felsefe var, eğer "Ur 'yanlış" iki yanlış argüman ile kedi kullanıyorsanız (ki, " cat"). - Dennis Williamson
ve asla ikinci EOF girintisi .... (baş patlamalarla ilgili çoklu masa) - IljaBek
Yukarıdaki ifadeyi kullanmaya çalıştım. set -e. Görünüyor read her zaman sıfırdan döner. Bu davranışı kullanarak kalınlaştırabilirsiniz. ! read -d ....... - krissi
Ve eğer bu çok satırlı kullanıyorsanız String bir dosyaya yazmak için değişken, "QUOTES" gibi değişkeni echo "${String}" > /tmp/multiline_file.txt veya echo "${String}" | tee /tmp/multiline_file.txt. Bunu bulmak için bir saatten fazla sürdü. - Aditya


Neredeyse oradaydın. Ya sen kedi dizginizin montajı için ya da bütün dizgeyi alıntılarsınız (bu durumda dizenin içindeki alıntılardan kaçmak zorunda kalırsınız):

#!/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}"

25
2017-10-08 11:14



Ne yazık ki, "Raphael'in" deki kesme işareti ilkini işe yaramaz hale getiriyor. - Dennis Williamson
Her iki ödev de sonunda benim için çalışır. VAR1'deki tek alıntı bir sorun olmamalıdır (en azından bash için). Belki sözdizimi vurgulayarak yanıldınız mı? - joschi
Bir komut dosyasında çalışır, ancak Bash komut isteminde değil. Daha açık olmamak için üzgünüm. - Dennis Williamson
EOF olarak alıntı yapmak daha iyidir 'EOF' veya "EOF"Aksi takdirde kabuk değişkenleri ayrıştırılacaktır. - Stanislav German-Evtushenko


#!/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}"

Bu Bourne kabuk ortamında iyi çalışmalı


9
2017-09-05 15:54



+1 bu çözüm, $ {foo} gibi değişken değiştirmeye izin verir - Offirmo
Upside: sh uyumlu. Dezavantajı: backticks, bash'ta önerilmemektedir. Şimdi sh ve bash arasında seçim yapmak zorunda kalsaydım ... - Zenexer
ne zamandan beri backticks önerilmiyor / reddediliyor? sadece merak - Alexander Mills


Yine aynı şeyi yapmanın başka bir yolu ...

Değişkenleri ve özel kullanmayı severim <<- kim düşüyor listeleme komut satırı girintisine izin vermek için her satırın başlangıcında:

#!/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

uyarı: hayır yok boşluk önce eof ama sadece listeleme.

<?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>
Bazı açıklamalar:
  • mapfile tümünü oku burada belge bir dizide.
  • sözdizimi "${Pattern[*]}" bu diziyi bir dizeye dönüştürür.
  • kullanırım IFS=";" Çünkü yok ; gerekli dizelerde
  • Sözdizimi while IFS=";" read file ... önlemek IFS komut dosyasının geri kalanı için değiştirilmek üzere. Bu sadece read değiştirilmiş kullanın IFS.
  • çatal yok.

4
2017-07-22 13:45



Bunu not et mapfile Bash 4 veya üstü gerektirir. Ve sözdizimi "${Pattern[*]}" diziyi bir dizeye çevirir ne zaman tırnak içinde (örnek kodda gösterildiği gibi). - Dennis Williamson
Evet, bash 4 çok iyiydi yeni bu soru sorulduğunda. - F. Hauri


Diğer cevapların çoğunda çok fazla köşe durumu var.

Alanlar, sekmeler, IFS vb. İle ilgili hiçbir sorun olmadığından emin olmak için daha iyi bir yaklaşım "heredoc" yapısını kullanmaktır, ancak heredoc'un içeriğini kodlamak uuencode Burada açıklandığı gibi:

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


2
2018-05-17 09:10