Saya sedang menulis di skrip pabrik skrip besar yang menghasilkan banyak skrip pemeliharaan untuk server saya.
Sampai sekarang saya menulis beberapa baris yang perlu ditulis dalam satu baris dengan echo -ne
misalnya
echo -n "if (( " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
# Generate exitCode check for each Server
IFS=" "
COUNT=0
while read -r name ipAddr
do
if(($COUNT != 0))
then
echo -n " || " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
fi
echo -n "(\$"$name"_E != 0 && \$"$name"_E != 1)" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
COUNT=$((COUNT+1))
JOBSDONE=$((JOBSDONE+1))
updateProgress $JOBCOUNT $JOBSDONE
done <<< "$(sudo cat /root/.virtualMachines)"
echo " ))" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
ini menghasilkan saya (jika ada misalnya 2 server di file konfigurasi saya) seperti kode
if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))
Semua blok kode lain yang tidak memerlukan penulisan inline kode yang saya hasilkan dengan heredocs ini karena saya menemukan cara yang lebih baik untuk menulis dan memelihara. Misal setelah kode atas saya memiliki sisanya dihasilkan seperti
cat << EOF | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
then
# Print out ExitCode legend
echo " ExitCode 42 - upgrade failed"
echo " ExitCode 43 - Upgrade failed"
echo " ExitCode 44 - Dist-Upgrade failed"
echo " ExitCode 45 - Autoremove failed"
echo ""
echo ""
fi
EOF
Jadi blok kode akhir terlihat seperti
if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))
then
# Print out ExitCode legend
echo " ExitCode 42 - upgrade failed"
echo " ExitCode 43 - Upgrade failed"
echo " ExitCode 44 - Dist-Upgrade failed"
echo " ExitCode 45 - Autoremove failed"
echo ""
echo ""
fi
Pertanyaan saya:
Adakah cara heredoc berperilaku serupa echo -ne
tanpa simbol end-of-line?
sudo
skrip yang salah: Jalankan keseluruhan skrip sebagai root!sudo -u USERNAME
pada yang bukan, lihat Bagaimana cara menjalankan perintah 'sudo' dalam naskah? .sudo
tanpa nama pengguna meminta kata sandi, kecuali jika Anda mengetikkannya ada penundaan. Lebih buruk lagi jika Anda tidak menjalankan skrip di terminal, maka Anda bahkan tidak bisa melihat permintaan kata sandi dan itu tidak akan berfungsi. Thesudo -u
Pendekatan tidak memiliki masalah ini.Jawaban:
Tidak, heredoc selalu berakhir pada baris baru. Tetapi Anda masih dapat menghapus baris baru terakhir, misalnya dengan Perl:
-p
membaca input baris demi baris, menjalankan kode yang ditentukan-e
, dan mencetak baris (mungkin dimodifikasi)sumber
Jawaban singkatnya adalah bahwa heredoc dan herestrings hanya dibangun dengan cara itu, jadi tidak ada - sini-doc dan herestring akan selalu menambahkan baris baru dan tidak ada pilihan atau cara asli untuk menonaktifkannya (mungkin akan ada rilis bash di masa mendatang?).
Namun, salah satu cara untuk mendekatinya melalui cara bash-only adalah membaca apa yang diberikan heredoc melalui
while IFS= read -r
metode standar , tetapi menambahkan penundaan dan mencetak baris terakhir melaluiprintf
tanpa baris baru. Inilah yang bisa dilakukan seseorang dengan bash-only:Apa yang Anda lihat di sini adalah loop sambil biasa dengan
IFS= read -r line
pendekatan, namun setiap baris disimpan ke dalam variabel dan dengan demikian tertunda (jadi kami melewatkan pencetakan baris pertama, menyimpannya, dan mulai mencetak hanya ketika kami membaca baris kedua). Dengan begitu kita dapat menangkap baris terakhir, dan ketika pada iterasi berikutnyaread
mengembalikan status keluar 1, saat itulah kita mencetak baris terakhir tanpa baris baru viaprintf
. Verbose? Iya. Tapi berhasil:Perhatikan
$
karakter cepat didorong ke depan, karena tidak ada baris baru. Sebagai bonus, solusi ini adalah portable dan POSIX-ish, sehingga harus bekerja diksh
dandash
juga.sumber
Saya sarankan Anda mencoba pendekatan yang berbeda. Alih-alih menyatukan skrip yang dibuat dari beberapa pernyataan gema dan heredocs. Saya sarankan Anda mencoba menggunakan heredoc tunggal.
Anda dapat menggunakan ekspansi variabel dan mengganti perintah di dalam heredoc. Seperti dalam contoh ini:
Saya menemukan bahwa ini sering mengarah pada hasil akhir yang jauh lebih mudah dibaca daripada memproduksi sepotong demi sepotong.
Sepertinya Anda lupa
#!
baris di awal skrip Anda. The#!
line adalah wajib di setiap script diformat dengan benar. Mencoba menjalankan skrip tanpa#!
baris hanya akan berfungsi jika Anda memanggilnya dari shell yang bekerja di sekitar skrip yang diformat dengan buruk, dan bahkan dalam kasus itu mungkin akan ditafsirkan oleh shell yang berbeda dari yang Anda inginkan.sumber
#!
tapi blok kode saya hanya satu cuplikan dari skrip 2000 baris;) Saya tidak melihat sekarang bagaimana saran Anda memecahkan masalah saya menghasilkan satu baris kode dalam loop sementara ...$( ...command...)
di dalam heredoc, untuk memasukkan output dari perintah-perintah inline pada titik itu di heredoc; (3) Bash memiliki variabel array, yang Anda dapat memperluas inline, dan menggunakan substitusi untuk menambahkan hal-hal di awal / akhir jika perlu. Bersama-sama ini membuat saran kasperd jauh lebih kuat (dan skrip Anda berpotensi jauh lebih mudah dibaca).Heredocs selalu berakhir dengan karakter baris baru tetapi Anda dapat menghapusnya. Cara termudah yang saya tahu adalah dengan
head
program ini:sumber
-c
juga mengambil nilai negatif! Seperti itu bahkan lebih daripearl
solusinyaAnda dapat menghapus baris baru dengan cara apa pun yang Anda suka, mem-piping ke
tr
mungkin paling sederhana. Ini tentu saja akan menghapus semua baris baru.Tetapi, jika pernyataan yang Anda bangun tidak mengharuskan itu, ekspresi aritmatika
(( .. ))
harus berfungsi dengan baik meskipun berisi baris baru.Jadi, Anda bisa melakukannya
memproduksi
Membangunnya dalam satu lingkaran masih membuat jelek. Ada di
|| 0
sana tentu saja sehingga kita tidak perlu kasus khusus baris pertama atau terakhir.Juga, Anda memiliki itu
| sudo tee ...
di setiap output. Saya pikir kita bisa menyingkirkan itu dengan membuka pengalihan hanya sekali (dengan substitusi proses), dan menggunakannya untuk pencetakan nanti:Dan terus terang, saya masih berpikir bahwa membangun nama variabel dari variabel dalam skrip luar (seperti itu
\$${name}_E
) agak jelek, dan mungkin harus diganti dengan array asosiatif .sumber