Apa yang str=$'Hello World\n===========\n'disebut sintaksis ? substitusi variabel?
zengr
5
@ zengr: Ini disebut kutipan ANSI-C , dan juga didukung di zshdan ksh; namun, ini BUKAN sesuai POSIX.
mklement0
4
@ mkelement0, ini berasal dari ksh93, juga didukung oleh zsh, bash, mksh dan FreeBSD sh, dan dimasukkannya dalam revisi utama berikutnya dari POSIX sedang dalam diskusi
Stéphane Chazelas
1
Tampaknya tidak bekerja dengan tanda kutip ganda? misalnya str=$"My $PET eats:\n$PET food"? Pendekatan ini bekerja untuk tanda kutip ganda
Brad Parks
31
Anda dapat menempatkan baris baru literal dalam tanda kutip tunggal (di shell gaya Bourne / POSIX).
str='Hello World
===========
'
Untuk string multiline, di sini dokumen sering kali nyaman. String diumpankan sebagai input ke perintah.
mycommand <<'EOF'HelloWorld===========
EOF
Jika Anda ingin menyimpan string dalam suatu variabel, gunakan catperintah dalam substitusi perintah. Karakter baris baru di akhir string akan dilucuti oleh substitusi perintah. Jika Anda ingin mempertahankan baris baru, letakkan sumbat di ujungnya dan cabut kemudian. Di shell yang sesuai dengan POSIX, Anda dapat menulis str=$(cat <<'EOF'); str=${str%a}diikuti oleh heredoc yang tepat, tetapi bash membutuhkan heredoc untuk muncul sebelum tanda kurung penutup.
str=$(cat <<'EOF'HelloWorld===========
a
EOF
); str=${str%a}
Di ksh, bash, dan zsh, Anda dapat menggunakan $'…'formulir yang dikutip untuk memperluas garis miring terbalik di dalam tanda kutip.
Saya menggunakan GNU bash 4.1.5, dan str=$(cat <<'EOF')tidak berfungsi sebagaimana mestinya .. )Kebutuhan untuk ditempatkan pada baris berikutnya setelah akhir-dok EOF.. tetapi meskipun demikian, ia kehilangan baris tambahan karena Command Pengganti.
Peter.O
@ Fred Poin bagus, saya sudah menjelaskan tentang baris baru dan kode yang ditampilkan yang bekerja di bash. Saya pikir ini adalah bug dalam bash, meskipun jujur saat membaca ulang spesifikasi POSIX, saya merasa tidak jelas bahwa perilakunya diamanatkan ketika << ada di dalam substitusi perintah dan heredoc tidak.
Gilles 'SO- stop being evil'
Hal-hal hebat; untuk melestarikan trailing (dan memimpin) \ninstance bashketika mengambil-doc di sini dalam variabel, pertimbangkan IFS= read -r -d '' str <<'EOF'...sebagai alternatif untuk pendekatan stopper (lihat jawaban saya).
BTW. Anda tidak memerlukan final \ n, karena echoakan secara otomatis menambahkannya, kecuali jika Anda menentukan -n. (Namun, beban utama dari pertanyaan, adalah bagaimana memasukkan baris baru ini ke dalam variabel).
Peter.O
+1 Dari semua solusi, yang ini paling langsung dan paling sederhana.
Hai Vu
echo -e tidak berfungsi di OS X
Greg M. Krsak
2
@GregKrsak: Dalam bash, echo -etidak bekerja pada OS X - itu karena echomerupakan bash builtin (bukan executable eksternal) dan bahwa builtin tidak mendukung -e. (Sebagai bawaan, itu harus bekerja pada semua platform yang dijalankan bash; secara kebetulan, echo -ebekerja di dalam kshdan zshjuga). Sebaliknya, utilitas eksternalecho pada OS X - /bin/echo- memang tidak mendukung -e.
mklement0
4
Jika Anda membutuhkan baris baru dalam skrip Anda berkali-kali, Anda bisa mendeklarasikan variabel global yang memegang baris baru. Dengan begitu Anda bisa menggunakannya dalam string yang dikutip ganda (ekspansi variabel).
NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"
Bagus! Ini dapat dimasukkan dalam variabel menggunakan tanda kutip ganda, misalnya"My dog eats:${NL}dog food"
Brad Parks
Ini berhasil untuk saya. Saat menggunakan skrip bash untuk menggabungkan string yang secara otomatis disalin ke clipboard untuk ditempelkan di tempat lain, pendekatan ini bekerja untuk menambahkan baris baru pada hasil yang dihasilkan.
Ville
3
Dari semua diskusi, berikut adalah cara paling sederhana bagi saya:
bash$ str="Hello World
==========="
bash$ echo "$str"HelloWorld===========
The gema perintah harus menggunakan tanda kutip ganda .
Jika Anda menggunakan bashdan lebih suka menggunakan baris baru untuk keterbacaan , readadalah opsi lain untuk menangkap dokumen di sini dalam variabel , yang (seperti solusi lain di sini) tidak memerlukan penggunaan subkulit.
# 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 \nHelloWorld===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"[HelloWorld===========]
-rmemastikan bahwa readtidak menginterpretasikan input (secara default, itu akan memperlakukan backslash khusus, tetapi itu jarang diperlukan).
-d ''menetapkan pembatas "record" menjadi string kosong, menyebabkan readpembacaan seluruh input sekaligus (bukan hanya satu baris).
Perhatikan bahwa dengan meninggalkan $IFS(pemisah bidang internal) pada pengaturan standarnya, $' \t\n'(spasi, tab, baris baru), spasi spasi apa pun yang memimpin dan tertinggal dipangkas dari nilai yang ditetapkan $str, yang mencakup baris baru di sini-doc.
(Perhatikan bahwa meskipun tubuh di sini-doc mulai pada baris setelah pembatas mulai (di 'EOF'sini), itu tidak mengandung baris baru yang memimpin ).
Biasanya, ini adalah perilaku yang diinginkan, tetapi jika Anda ingin yang mengikuti baris baru, gunakan IFS= read -r -d ''bukan hanya read -r -d '', tetapi perhatikan bahwa spasi spasi apa pun yang memimpin dan tertinggal kemudian dipertahankan.
(Perhatikan bahwa menambahkan IFS= langsung ke readperintah berarti bahwa penugasan hanya berlaku selama perintah itu saja, sehingga tidak perlu mengembalikan nilai sebelumnya.)
Menggunakan dokumen-sini juga memungkinkan Anda untuk menggunakan indentasi opsional untuk mematikan string multiline agar mudah dibaca:
# 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.HelloWorld===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.# Note how the leading tabs were stripped.
$ echo "$str"[HelloWorld===========]
Menempatkan di -antara <<dan pembuka di sini-doc pembatas ( 'EOF', di sini) menyebabkan karakter tab utama dihapus dari badan di sini-doc dan bahkan pembatas penutup, tetapi perlu dicatat bahwa ini hanya bekerja dengan karakter tab yang sebenarnya , bukan spasi, jadi jika Anda Editor menerjemahkan penekanan tombol tab ke spasi, diperlukan kerja ekstra.
Seperti yang ditunjukkan Fred, dengan cara ini Anda akan kehilangan jejak "\ n". Untuk menetapkan variabel dengan urutan backslash diperluas, lakukan:
STR=$'Hello World\n===========\n\n'
mari kita mengujinya:
echo "[[$STR]]"
beri kami sekarang:
[[HelloWorld===========]]
Perhatikan, bahwa $ '' berbeda dari $ "". Yang kedua melakukan terjemahan sesuai dengan lokal saat ini. Untuk deital, lihat bagian QUOTING di man bash.
Jawaban:
Di dalamnya
bash
Anda bisa menggunakan sintaksKutipan tunggal yang didahului oleh a
$
adalah sintaks baru yang memungkinkan untuk memasukkan urutan escape dalam string.printf
Builtin juga memungkinkan untuk menyimpan output yang dihasilkan ke variabelKedua solusi tidak memerlukan subkulit.
Jika dalam hal-hal berikut Anda perlu mencetak string, Anda harus menggunakan tanda kutip ganda, seperti dalam contoh berikut:
karena ketika Anda mencetak string tanpa tanda kutip, baris baru dikonversi menjadi spasi.
sumber
str=$'Hello World\n===========\n'
disebut sintaksis ? substitusi variabel?zsh
danksh
; namun, ini BUKAN sesuai POSIX.str=$"My $PET eats:\n$PET food"
? Pendekatan ini bekerja untuk tanda kutip gandaAnda dapat menempatkan baris baru literal dalam tanda kutip tunggal (di shell gaya Bourne / POSIX).
Untuk string multiline, di sini dokumen sering kali nyaman. String diumpankan sebagai input ke perintah.
Jika Anda ingin menyimpan string dalam suatu variabel, gunakan
cat
perintah dalam substitusi perintah. Karakter baris baru di akhir string akan dilucuti oleh substitusi perintah. Jika Anda ingin mempertahankan baris baru, letakkan sumbat di ujungnya dan cabut kemudian. Di shell yang sesuai dengan POSIX, Anda dapat menulisstr=$(cat <<'EOF'); str=${str%a}
diikuti oleh heredoc yang tepat, tetapi bash membutuhkan heredoc untuk muncul sebelum tanda kurung penutup.Di ksh, bash, dan zsh, Anda dapat menggunakan
$'…'
formulir yang dikutip untuk memperluas garis miring terbalik di dalam tanda kutip.sumber
str=$(cat <<'EOF')
tidak berfungsi sebagaimana mestinya ..)
Kebutuhan untuk ditempatkan pada baris berikutnya setelah akhir-dokEOF
.. tetapi meskipun demikian, ia kehilangan baris tambahan karena Command Pengganti.\n
instancebash
ketika mengambil-doc di sini dalam variabel, pertimbangkanIFS= read -r -d '' str <<'EOF'...
sebagai alternatif untuk pendekatan stopper (lihat jawaban saya).Apakah Anda menggunakan "gema"? Coba "echo -e".
sumber
echo
akan secara otomatis menambahkannya, kecuali jika Anda menentukan -n. (Namun, beban utama dari pertanyaan, adalah bagaimana memasukkan baris baru ini ke dalam variabel).bash
,echo -e
tidak bekerja pada OS X - itu karenaecho
merupakan bash builtin (bukan executable eksternal) dan bahwa builtin tidak mendukung-e
. (Sebagai bawaan, itu harus bekerja pada semua platform yang dijalankan bash; secara kebetulan,echo -e
bekerja di dalamksh
danzsh
juga). Sebaliknya, utilitas eksternalecho
pada OS X -/bin/echo
- memang tidak mendukung-e
.Jika Anda membutuhkan baris baru dalam skrip Anda berkali-kali, Anda bisa mendeklarasikan variabel global yang memegang baris baru. Dengan begitu Anda bisa menggunakannya dalam string yang dikutip ganda (ekspansi variabel).
sumber
$''
perlu subkulit?"My dog eats:${NL}dog food"
Dari semua diskusi, berikut adalah cara paling sederhana bagi saya:
The gema perintah harus menggunakan tanda kutip ganda .
sumber
Untuk melengkapi jawaban hebat yang sudah ada:
Jika Anda menggunakan
bash
dan lebih suka menggunakan baris baru untuk keterbacaan ,read
adalah opsi lain untuk menangkap dokumen di sini dalam variabel , yang (seperti solusi lain di sini) tidak memerlukan penggunaan subkulit.-r
memastikan bahwaread
tidak menginterpretasikan input (secara default, itu akan memperlakukan backslash khusus, tetapi itu jarang diperlukan).-d ''
menetapkan pembatas "record" menjadi string kosong, menyebabkanread
pembacaan seluruh input sekaligus (bukan hanya satu baris).Perhatikan bahwa dengan meninggalkan
$IFS
(pemisah bidang internal) pada pengaturan standarnya,$' \t\n'
(spasi, tab, baris baru), spasi spasi apa pun yang memimpin dan tertinggal dipangkas dari nilai yang ditetapkan$str
, yang mencakup baris baru di sini-doc.(Perhatikan bahwa meskipun tubuh di sini-doc mulai pada baris setelah pembatas mulai (di
'EOF'
sini), itu tidak mengandung baris baru yang memimpin ).Biasanya, ini adalah perilaku yang diinginkan, tetapi jika Anda ingin yang mengikuti baris baru, gunakan
IFS= read -r -d ''
bukan hanyaread -r -d ''
, tetapi perhatikan bahwa spasi spasi apa pun yang memimpin dan tertinggal kemudian dipertahankan.(Perhatikan bahwa menambahkan
IFS=
langsung keread
perintah berarti bahwa penugasan hanya berlaku selama perintah itu saja, sehingga tidak perlu mengembalikan nilai sebelumnya.)Menggunakan dokumen-sini juga memungkinkan Anda untuk menggunakan indentasi opsional untuk mematikan string multiline agar mudah dibaca:
Menempatkan di
-
antara<<
dan pembuka di sini-doc pembatas ('EOF'
, di sini) menyebabkan karakter tab utama dihapus dari badan di sini-doc dan bahkan pembatas penutup, tetapi perlu dicatat bahwa ini hanya bekerja dengan karakter tab yang sebenarnya , bukan spasi, jadi jika Anda Editor menerjemahkan penekanan tombol tab ke spasi, diperlukan kerja ekstra.sumber
Anda perlu melakukannya dengan cara ini:
Memperbarui:
Seperti yang ditunjukkan Fred, dengan cara ini Anda akan kehilangan jejak "\ n". Untuk menetapkan variabel dengan urutan backslash diperluas, lakukan:
mari kita mengujinya:
beri kami sekarang:
Perhatikan, bahwa $ '' berbeda dari $ "". Yang kedua melakukan terjemahan sesuai dengan lokal saat ini. Untuk deital, lihat bagian QUOTING di
man bash
.sumber
keluaran:
sumber
result+=$foo$'\n'
?$(printf %s "$foo")
akan memangkas trailing karakter baris baru$foo
jika ada.