Bash'de çok satırlı bir dize nasıl çıkarılır?


250

Nasıl böyle birden çok yankı çağrıları kullanmadan Bash çok satırlı bir dize çıktısı:

echo "usage: up [--level <n>| -n <levels>][--help][--version]"
echo 
echo "Report bugs to: "
echo "up home page: "

Ben sadece Bash yerleşik kullanarak, bunu yapmak için taşınabilir bir yol arıyorum.


4
Yanlış bir çağrıya yanıt olarak bir kullanım mesajı çıkarıyorsanız, normalde bu mesajı standart çıktı yerine standart hataya gönderirsinizecho >&2 ...
Mark Reed

2
@MarkReed Kullanım mesajı yazılarak verilir --help(standart çıkışa geçmelidir).
helpermethod

Gelen diğerleri için, "burada belgeler" hakkında daha fazla bilgi mevcuttur: tldp.org/LDP/abs/html/here-docs.html
Jeffrey Martinez

printfGordon Davidson'dan tabanlı çözümü kontrol edin . echoYa da cattemelli yaklaşımların gölgesinde olmasına rağmen , bir çamurdan çok daha az gibi görünüyor. Kuşkusuz `printf 'sözdizimi bir öğrenme eğrisini temsil ediyor, ancak diğer dezavantajlara kulak vermek istiyorum (? Uyumluluk, performans? ...)
mjv

Yanıtlar:


296

Burada belgeler genellikle bu amaç için kullanılır.

cat << EOF
usage: up [--level <n>| -n <levels>][--help][--version]

Report bugs to: 
up home page:
EOF

Bash'in tüm versiyonları dahil olmak üzere Bourne'den türetilen tüm kabuklarda desteklenirler.


4
Evet, ama catyerleşik değil.
Mark Reed

8
@MarkReed: Bu doğru, ancak her zaman kullanılabilir (muhtemelen olağandışı koşullar dışında).
sonraki duyuruya kadar duraklatıldı.

6
+1 Thx. read -d '' help <<- EOF ...Bir değişken içine çok satırlı dize okumak için kullanarak sona erdi ve sonra sonucu yankılandı.
helpermethod

3
HEREDOC değişkenine kaydedebilir miyim?
chovy

177

ya da bunu yapabilirsiniz:

echo "usage: up [--level <n>| -n <levels>][--help][--version]

Report bugs to: 
up home page: "

1
@OliverWeiler: Dash ve Heirloom Bourne Kabuğu gibi Bourne mermilerinde bile çalışacak .
sonraki duyuruya kadar duraklatıldı.

6
Bir fonksiyonda buna ihtiyacınız varsa harika değil çünkü 1) dizeyi dosyanızın soluna kadar uzatmanız veya 2) kodunuzun geri kalanıyla aynı hizada olmasını sağlamanız gerekir, ancak daha sonra girintiler de
sg

43

Bu sayfadaki anlayışlı cevaplardan esinlenerek, en basit ve daha esnek olanı düşündüğüm karışık bir yaklaşım oluşturdum. Ne düşünüyorsun?

İlk olarak, bir değişkendeki kullanımı tanımladım, bu da onu farklı bağlamlarda yeniden kullanmama izin veriyor. Biçim çok basit, neredeyse WYSIWYG, herhangi bir kontrol karakteri eklemeye gerek kalmadan. Bu benim için oldukça taşınabilir görünüyor (MacOS ve Ubuntu'da çalıştırdım)

__usage="
Usage: $(basename $0) [OPTIONS]

Options:
  -l, --level <n>              Something something something level
  -n, --nnnnn <levels>         Something something something n
  -h, --help                   Something something something help
  -v, --version                Something something something version
"

O zaman sadece

echo "$__usage"

veya daha da iyisi, parametreleri ayrıştırırken, sadece bir astarda yankılanabilirim:

levelN=${2:?"--level: n is required!""${__usage}"}

4
bu benim için yukarıdaki cevabın olmadığı bir senaryoda çalıştı (değişiklik yapmadan).
David Welch

3
Bu, \ t ve \ n gibi metinde bulmak ve çıktıyı komut dosyasındaki
sg

1
Bazı nedenlerden dolayı her şeyi benim için aynı hatta yazdırıyor: /
Nicolas de Fontenay

2
@Nicolas: İçinde çift tırnak kullanmak echo "$__usage"benim için gerekliydi. echo $__usageişe yaramadı.
Mario

24

-eSeçeneğini kullanın , ardından \ndizede yeni satır karakteri yazdırabilirsiniz .

Örnek (ama iyi olup olmadığından emin değilim)

Eğlenceli olan, bu -eseçeneğin hala kullanılabilir durumdayken MacOS'un kılavuz sayfasında belgelenmemiş olmasıdır . Linux'un kılavuz sayfasında belgelenmiştir .


6
Bu kılavuz sayfaları, Mac OS'de herhangi bir seçeneğin bulunmadığı sistem tarafından sağlanan echokomut içindir . bu sistemlerde bash kullandığınızda, yerleşik komutu devralır. Bunu davranıştaki farkı açıkça yazarak ve gözlemleyerek görebilirsiniz . Yerleşik belgelere bakmak için yazın . /bin/echo-eecho/bin/echo whateverhelp echo
Mark Reed

1
/bin/echogenellikle bir işletim sisteminden diğerine ve Bash yerleşkesinden farklıdır echo.
sonraki duyuruya kadar duraklatıldı.

@MarkReed: Daha sonra deneyeceğim, ama bilgi için teşekkürler. +1. Cevabımı burada bırakacağım, çünkü devam etmekte olan birçok iyi tartışma var.
nhahtdh

7
echo -etaşınabilir değildir - örneğin, bazı eko uygulamaları çıktının bir parçası olarak "-e" yi basar. Taşınabilirlik istiyorsanız bunun yerine printf kullanın. Örneğin, OS X 10.7.4'te / bin / echo bunu yapar. IIRC bash yerleşik yankısı da 10.5.0'ın altında garipti, ama detayları artık hatırlamıyorum.
Gordon Davisson

2
echo -ebeni daha önce ısırdı ... Kesinlikle kullanın printfveya catbir yorumlu. Bu <<-dokümanın varyantı özellikle güzel, çünkü çıktıda önde gelen girintiyi çıkarabilirsiniz, ancak komut dosyasında okunabilirlik için girintili
zbeekman

22

printfBir yorumda önerdiğimden , muhtemelen kullanımıyla ilgili bazı örnekler vermeliyim (bir kullanım mesajı yazdırmak için Dennis veya Chris'in cevaplarını kullanmam daha olasıdır). printfkullanmak biraz daha karmaşıktır echo. İlk argümanı, kaçışların (gibi \n) her zaman yorumlandığı bir biçim dizesidir ; ile başlayan biçim yönergeleri de içerebilir%herhangi bir ek argümanın nereye ve nasıl dahil edileceğini kontrol eden . Bir kullanım mesajı olarak kullanmak için iki farklı yaklaşım:

İlk olarak, iletinin tamamını biçim dizesine ekleyebilirsiniz:

printf "usage: up [--level <n>| -n <levels>][--help][--version]\n\nReport bugs to: \nup home page: \n"

Bunun aksine echo, son yeni satırı açıkça eklemeniz gerektiğini unutmayın . Ayrıca, mesaj herhangi bir %karakter içeriyorsa , olarak yazılmalıdır %%. Hata raporu ve ana sayfa adreslerini eklemek istiyorsanız, bunlar oldukça doğal olarak eklenebilir:

printf "usage: up [--level <n>| -n <levels>][--help][--version]\n\nReport bugs to: %s\nup home page: %s\n" "$bugreport" "$homepage"

İkinci olarak, her ek bağımsız değişkeni ayrı bir satıra yazdırmak için biçim dizesini kullanabilirsiniz:

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: " "up home page: "

Bu seçenekle hata raporu ve ana sayfa adreslerini eklemek oldukça açıktır:

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: $bugreport" "up home page: $homepage"

9

Girintili kaynak koduyla <<-da, baştaki sekmeleri (ancak baştaki boşlukları değil) yok saymak için kullanabilirsiniz (arkadaki çizgi ile). Örneğin bu:

if [ some test ]; then
    cat <<- xx
        line1
        line2
xx
fi

Girintili metni, önde gelen boşluk olmadan çıkarır:

line1
line2

Bu benim için işe yaramadı. Hangi kabuğu kullanıyorsun?
four43

Ubuntu 4.4.19 bash işe yaramadı. Satır1 ve satır2'den önceki aralığı kaldırmadı
four43

1
@ four43, Haklıydın. Önde gelen boşlukları kaldırmak için çalışmaz. Ancak, önde gelen sekmeleri kaldırır. Bu yüzden cevabımı sekmelerden ve boşluklardan boşluklara değil sekmelere düzelttim. Hata için üzgünüm. Kılavuzu kontrol ettim ve açıkça sekmelerin kaldırıldığını söylüyor. Bunu dikkatime sunduğunuz için teşekkürler.
Eliptik görünüm

0

@Jorge çözümünü kullanır ve her şeyin aynı satırda olduğunu görürseniz, değişkeni tırnak içine aldığınızdan emin olun:

echo $__usage

her şeyi tek bir satıra yazdıracak

echo "$__usage"

yeni satırları koruyacaktır.


Bu benim için işe yarayan tek çözüm. Printf çok şey yapıyor ve çok satırlı xml'imle, içeriği tamamen değiştirdiği için muhtemelen çok fazla kaçış gerektiriyor. Foo = cat <<EOF .... EOF&& echo "$ foo"
atarım
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.