Bash betiğindeki değişkenlere newlines nasıl eklenir


Yanıtlar:


73

Gelen bashsözdizimi kullanabilirsiniz

str=$'Hello World\n===========\n'

A'dan önce gelen tek tırnaklar $, dizelere kaçış dizileri eklenmesini sağlayan yeni bir sözdizimidir.

Ayrıca printfyerleşik sonuç bir çıktının değişkene kaydedilmesini sağlar.

printf -v str 'Hello World\n===========\n'

Her iki çözüm de bir deniz kabuğu gerektirmez.

Aşağıda dizgeyi yazdırmanız gerekiyorsa, aşağıdaki örnekte olduğu gibi çift tırnak kullanmanız gerekir:

echo "$str"

çünkü dizeyi tırnak işaretleri olmadan yazdırdığınızda, newline boşluklara dönüştürülür.


1
str=$'Hello World\n===========\n'Adı verilen sözdizimi nedir ? değişken ikame?
zengr,

5
@zengr: Bu denir ANSI-C alıntı ve aynı zamanda desteklenenler zshve ksh; ancak, POSIX uyumlu değil.
mklement0,

4
@ mkelement0, ksh93'ten geliyor, ayrıca zsh, bash, mksh ve FreeBSD sh tarafından da destekleniyor ve POSIX'in bir sonraki ana revizyonuna dahil edilmesi tartışılıyor
Stéphane Chazelas

1
Çift tırnak ile çalışmıyor gibi görünüyor mu? mesela str=$"My $PET eats:\n$PET food"? Bu yaklaşım çift ​​tırnak için işe yarar
Brad Parks

31

Kelimenin tam anlamıyla yeni satırları tek tırnak içine alabilirsiniz (herhangi bir Bourne / POSIX tarzı kabukta).

str='Hello World
===========
'

Çok satırlı bir dize için, burada belgeler genellikle uygundur. Dize bir komuta girdi olarak beslenir.

mycommand <<'EOF'
Hello World
===========
EOF

Dizeyi değişkende saklamak istiyorsanız, catkomutu bir komut yerine kullanın. Dizenin sonundaki yeni satır karakterleri, komut yerine koyularak sıyrılacaktır. Son satırları saklamak istiyorsanız, sonuna bir durdurucu yerleştirin ve daha sonra soyun. POSIX uyumlu mermilerde str=$(cat <<'EOF'); str=${str%a}heredoc'u uygun yazdıktan sonra yazabilirsiniz , ancak bash heredokun kapanış parantezinden önce görünmesini gerektirir.

str=$(cat <<'EOF'
Hello World
===========
a
EOF
); str=${str%a}

Ksh, bash ve zsh'da, $'…'alıntılar içinde ters eğik çizgi kaçışlarını genişletmek için belirtilen formu kullanabilirsiniz .

str=$'Hello World\n===========\n'

1
Ben GNU bash 4.1.5 kullanıyorum ve str=$(cat <<'EOF')olduğu gibi .. çalışmıyor )sonu doc sonraki satırda yerleştirilecek ihtiyaçlarını EOF.. ama buna rağmen, bu Komutanlığına bağlı sondaki yeni satır kaybeder İkame.
Peter.O

@fred İyi noktalar, izleyen yeni satırları ve bash'de çalışan kodları açıkladım. Ben bash bir hata olduğunu düşünüyorum, ancak POSIX spec yeniden okurken dürüst olmak gerekirse, << bir komut yerine geçtiğinde ve heredoc olmadığı zaman davranış zorunlu olduğunu açık değildir.
Gilles

Harika şeyler; Burada bir doc değişkeni yakalarken yakalanan (ve önde gelen) \nörnekleri korumak için, durdurucu yaklaşımına bir alternatif olarak bashdüşünün IFS= read -r -d '' str <<'EOF'...(cevabımı bakın).
mklement0,

8

"Eko" kullanıyor musunuz? "Echo-e" yi dene.

echo -e "Hello World\n===========\n"

2
BTW. Finaline ihtiyacınız yok, çünkü echo-n belirtmediğiniz sürece otomatik olarak bir tane ekleyecektir. (Bununla birlikte, sorunun asıl amacı, bu yeni satırları bir değişkene nasıl getireceğimizdir).
Peter.O

+1 Tüm çözümlerden en doğrudan ve en basit olanı budur.
Hai Vu

echo -e OS X'de çalışmıyor
Greg M. Krsak

2
@GregKrsak: In bash, echo -e yapar OS X üzerinde çalışmaya - bunun nedeni echobir bash olan yerleşik (ziyade harici çalıştırılabilir) ve bu yerleşik destekliyor -e. (Bir yerleşik olarak, bash'ın çalıştığı tüm platformlarda echo -eçalışmalıdır ; tesadüfen çalışır kshve çalışır zsh). Buna karşılık, bununla birlikte, dış echoyarar OS X üzerinde - /bin/echo- aslında yok değil desteklemek -e.
mklement0,

3

Komut dosyanızda newline'lara birçok kez gereksinim duyarsanız, newline'ı tutan global bir değişken tanımlayabilirsiniz. Bu şekilde çift tırnaklı dizelerde (değişken açılımlar) kullanabilirsiniz.

NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"

Neden $''bir deniz kabuğu gerektiriyor?
Mat,

Üzgünüm, cevap yanlış.
pihentagy

Seçmenlerden açıklama isteyebilir miyim?
pihentagy

Güzel! Bu, çift tırnak kullanan değişkenlere dahil edilebilir, örneğin"My dog eats:${NL}dog food"
Brad Parks

3

Tüm tartışmalardan, işte benim için en basit yol:

bash$ str="Hello World
==========="
bash$ echo "$str"
Hello World
===========

Yankı komut kullanmalısınız çift tırnak .


3

Mevcut harika cevapları tamamlamak için:

Kullanıyorsanız bashve okunabilirlik için gerçek yeni satırları kullanmayı tercih ederseniz , burada bir dokümanı bir değişkende yakalamakread için başka bir seçenektir (buradaki diğer çözümler gibi) bir alt kabuk kullanımı gerektirmez.

# Reads a here-doc, trimming leading and trailing whitespace.
# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF'   # Use `IFS= read ...` to preserve the trailing \n
Hello World
===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"
[Hello World
===========]
  • -rreadbunun girişi yorumlamamasını sağlar (varsayılan olarak ters eğik çizgilere özel davranır, ancak bu nadiren gereklidir).

  • -d ''"kayıt" sınırlayıcısını boş bir dizeye ayarlar, bu readda girişin tamamını aynı anda okumasına neden olur (sadece tek bir satır yerine).

$IFS(İç alan ayırıcıyı) varsayılan değerinde $' \t\n'(boşluk, sekme, yeni satır) bırakarak , öndeki ve sondaki boşlukların,$str burada-doc'ın son satırını da içeren atanmış değerinden kesildiğini unutmayın.
(Burada-doktorun vücut hattı üzerinde başlar halde unutmayın sonra başlangıç sınırlayıcı ( 'EOF'burada), bu yok değil işaretini içerir lider satırsonu).

Genellikle, bu istenen davranıştır, ancak yeni satır sondaki bunu istiyorum yoksa, kullanmak IFS= read -r -d ''yerine sadece read -r -d ''ama unutmayın herhangi baştaki ve sondaki boşluk sonra korunur.
( IFS= Doğrudan readkomuta hazırlanmanın, atamanın yalnızca bu komut sırasında geçerli olduğu anlamına gelir, bu nedenle önceki değeri geri yüklemeye gerek yoktur.)


Bir here-doc kullanmak , isteğe bağlı olarak çok satırlı dizgiyi okunabilirlik için çıkarmak üzere girintiyi kullanmanızı sağlar :

# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF' # NOTE: Only works if the indentation uses actual tab (\t) chars.
    Hello World
    ===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.
# Note how the leading tabs were stripped.
$ echo "$str"
[Hello World
===========]

Yerleştirme -arasında <<ve burada-doc açılış sınırlayıcı ( 'EOF'burada) sekmesi karakterleri burada-doc beden ve hatta kapanış sınırlayıcı çıkarılmalı yol açan neden olur, ancak bu dikkat do yalnızca çalışır fiili sekme karakterleri , değil boşluklar, eğer öyleyse senin editör tab tuşlarını boşluklara çevirir, fazladan çalışmaya ihtiyaç vardır.


-1

bu şekilde yapmanız gerekir:

STR=$(echo -ne "Hello World\n===========\n")

Güncelleme:

Fred'in işaret ettiği gibi, bu şekilde "\ n" izini kaybedersiniz. Ters eğik çizgi dizileri içeren değişken atamak için şunları yapın:

STR=$'Hello World\n===========\n\n'

hadi test edelim:

echo "[[$STR]]"

bize şimdi veriyor:

[[Hello World
===========

]]

Not $ '', $ "" den farklı. İkincisi, geçerli yerel ayarlara göre çeviri yapar. İlahiyat için, bkz man bash.


-2
#!/bin/bash

result=""

foo="FOO"
bar="BAR"

result+=$(printf '%s' "$foo")$'\n'
result+=$(printf '%s' "$bar")$'\n'

echo "$result"
printf '%s' "$result"

çıktı:

FOO
BAR

FOO
BAR

1
Neden basitçe değil result+=$foo$'\n'? eğer varsa $(printf %s "$foo")sondaki yeni satır karakterlerini keserdi $foo.
Stéphane Chazelas 26:16

Kod için açıklama yok, aksi takdirde bana iyi geliyor.
şey, bir şey
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.