Ketika Anda sampai di leher Anda dalam buaya, mudah untuk melupakan bahwa tujuannya adalah untuk mengeringkan rawa.
- Pepatah populer
Pertanyaannya adalah tentang echo, namun sebagian besar jawaban sejauh ini berfokus pada bagaimana menyelinap set +xperintah. Ada solusi yang lebih sederhana, lebih langsung:
{ echo "Message"; } 2> /dev/null
(Saya mengakui bahwa saya mungkin tidak memikirkan { …; } 2> /dev/null
jika saya tidak melihatnya dalam jawaban sebelumnya.)
Ini agak rumit, tetapi, jika Anda memiliki blok echoperintah berturut-turut , Anda tidak perlu melakukannya pada masing-masing secara individual:
{
echo "The quick brown fox"
echo "jumps over the lazy dog."
} 2> /dev/null
Perhatikan bahwa Anda tidak perlu titik koma saat memiliki baris baru.
Anda dapat mengurangi beban pengetikan dengan menggunakan ide kenorb untuk
membuka /dev/nullsecara permanen pada deskriptor file non-standar (misalnya, 3) dan kemudian mengatakan 2>&3alih-alih 2> /dev/nullsepanjang waktu.
Empat jawaban pertama pada saat penulisan ini memerlukan melakukan sesuatu yang istimewa (dan, dalam kebanyakan kasus, rumit)
setiap kali Anda melakukan suatu echo. Jika Anda benar-benar ingin semua echo perintah untuk menekan jejak eksekusi (dan mengapa Anda tidak melakukannya?), Anda dapat melakukannya secara global, tanpa mengeluarkan banyak kode. Pertama, saya perhatikan bahwa alias tidak dilacak:
$ myfunc()
> {
> date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016 0:00:00 AM # Happy Halloween!
$ myfunc
+ myfunc # Note that function call is traced.
+ date
Mon, Oct 31, 2016 0:00:01 AM
$ myalias
+ date # Note that it doesn’t say + myalias
Mon, Oct 31, 2016 0:00:02 AM
(Perhatikan bahwa cuplikan skrip berikut berfungsi jika shebang #!/bin/sh, bahkan jika /bin/shtautan ke bash. Tetapi, jika shebang adalah #!/bin/bash, Anda perlu menambahkan shopt -s expand_aliasesperintah untuk membuat alias agar bekerja dalam skrip.)
Jadi, untuk trik pertama saya:
alias echo='{ set +x; } 2> /dev/null; builtin echo'
Sekarang, ketika kita mengatakan echo "Message", kita memanggil alias, yang tidak bisa dilacak. Alias mematikan opsi jejak, sementara menekan pesan jejak dari setperintah (menggunakan teknik yang disajikan pertama dalam jawaban user5071535 ), dan kemudian menjalankan echoperintah yang sebenarnya . Ini memungkinkan kita mendapatkan efek yang mirip dengan jawaban user5071535 tanpa perlu mengedit kode di setiap echo perintah. Namun, mode jejak daun ini dimatikan. Kami tidak dapat memasukkan set -xalias ke (atau setidaknya tidak mudah) karena alias hanya memungkinkan string untuk diganti dengan kata; tidak ada bagian dari string alias yang dapat disuntikkan ke perintah
setelah argumen (misalnya, "Message"). Jadi, misalnya, jika skripnya berisi
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date
hasilnya akan
+ date
Mon, Oct 31, 2016 0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016 0:00:04 AM # Note that it doesn’t say + date
jadi Anda masih perlu mengaktifkan kembali opsi jejak setelah menampilkan pesan - tetapi hanya sekali setelah setiap blokecho perintah berturut-turut :
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date
Akan lebih baik jika kita bisa membuat set -xotomatis setelah echo- dan kita bisa, dengan sedikit tipu daya. Tetapi sebelum saya sajikan itu, pertimbangkan ini. OP dimulai dengan skrip yang menggunakan #!/bin/sh -exshebang. Secara implisit pengguna dapat menghapus xdari shebang dan memiliki skrip yang bekerja secara normal, tanpa penelusuran jejak. Alangkah baiknya jika kita bisa mengembangkan solusi yang mempertahankan properti itu. Beberapa jawaban pertama di sini gagal properti itu karena mereka melacak "kembali" pada setelah echopernyataan, tanpa syarat, tanpa memperhatikan apakah itu sudah aktif.
Jawaban ini jelas gagal mengenali masalah itu, karena ia menggantikan echooutput dengan jejak output; oleh karena itu, semua pesan hilang jika penelusuran dimatikan. Saya sekarang akan menyajikan solusi yang ternyata melacak kembali setelah echopernyataan bersyarat - hanya jika sudah aktif. Menurunkan versi ini menjadi solusi yang mengubah penelusuran "kembali" tanpa syarat adalah sepele dan dibiarkan sebagai latihan.
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
builtin echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
$-adalah daftar opsi; gabungan huruf yang sesuai dengan semua opsi yang ditetapkan. Misalnya, jika edan xopsi diatur, maka $-akan ada serakan huruf yang mencakup edan x. Alias baru saya (di atas) menyimpan nilai $-sebelum mematikan penelusuran. Kemudian, dengan pelacakan dimatikan, itu melemparkan kontrol ke fungsi shell. Fungsi itu melakukan yang sebenarnya echo
dan kemudian memeriksa untuk melihat apakah xopsi dihidupkan ketika alias dipanggil. Jika opsi diaktifkan, fungsi akan mengaktifkannya kembali; jika tidak aktif, fungsi akan mati.
Anda dapat memasukkan tujuh baris di atas (delapan, jika Anda menyertakan a shopt) di awal skrip dan biarkan sisanya sendiri.
Ini akan memungkinkan Anda
- untuk menggunakan salah satu dari garis shebang berikut:
#! / bin / sh -ex
#! / bin / sh -e
#! / bin / sh –x
atau sekadar polos#! / bin / sh
dan itu harus bekerja seperti yang diharapkan.
- untuk memiliki kode seperti
(shebang)
perintah 1
perintah 2
perintah 3
set -x
perintah 4
perintah 5
perintah 6
set + x
perintah 7
perintah 8
perintah 9
dan
- Perintah 4, 5, dan 6 akan dilacak - kecuali salah satunya adalah
echo, dalam hal ini akan dieksekusi tetapi tidak dilacak. (Tetapi meskipun perintah 5 adalah echo, perintah 6 masih akan dilacak.)
- Perintah 7, 8, dan 9 tidak akan dilacak. Bahkan jika perintah 8 adalah
echo, perintah 9 masih tidak akan dilacak.
- Perintah 1, 2, dan 3 akan dilacak (seperti 4, 5, dan 6) atau tidak (seperti 7, 8, dan 9) tergantung pada apakah shebang termasuk
x.
PS Saya telah menemukan bahwa, di sistem saya, saya dapat meninggalkan builtinkata kunci di jawaban tengah saya (yang hanya alias untuk echo). Ini tidak mengejutkan; bash (1) mengatakan bahwa, selama ekspansi alias, ...
... kata yang identik dengan alias yang diperluas tidak diperluas untuk kedua kalinya. Ini berarti bahwa seseorang dapat alias lsuntuk ls -F, misalnya, dan bash tidak mencoba memperluas teks pengganti secara rekursif.
Tidak terlalu mengejutkan, jawaban terakhir (yang dengan echo_and_restore) gagal jika builtinkata kunci dihilangkan 1 . Tapi, anehnya itu berfungsi jika saya menghapus builtindan mengganti urutan:
echo_and_restore() {
echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
__________
1 Tampaknya menimbulkan perilaku yang tidak terdefinisi. Saya telah melihat
- loop tak terbatas (mungkin karena rekursi tak terbatas),
- sebuah
/dev/null: Bad addresspesan kesalahan, dan
- dump inti.
echo +x; echo "$*"; echo -xdalam alias, saya ingin melihatnya.