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 +x
perintah. 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 echo
perintah 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/null
secara permanen pada deskriptor file non-standar (misalnya, 3) dan kemudian mengatakan 2>&3
alih-alih 2> /dev/null
sepanjang 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/sh
tautan ke bash. Tetapi, jika shebang adalah #!/bin/bash
, Anda perlu menambahkan shopt -s expand_aliases
perintah 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 set
perintah (menggunakan teknik yang disajikan pertama dalam jawaban user5071535 ), dan kemudian menjalankan echo
perintah 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 -x
alias 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 -x
otomatis setelah echo
- dan kita bisa, dengan sedikit tipu daya. Tetapi sebelum saya sajikan itu, pertimbangkan ini. OP dimulai dengan skrip yang menggunakan #!/bin/sh -ex
shebang. Secara implisit pengguna dapat menghapus x
dari 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 echo
pernyataan, tanpa syarat, tanpa memperhatikan apakah itu sudah aktif.
Jawaban ini jelas gagal mengenali masalah itu, karena ia menggantikan echo
output dengan jejak output; oleh karena itu, semua pesan hilang jika penelusuran dimatikan. Saya sekarang akan menyajikan solusi yang ternyata melacak kembali setelah echo
pernyataan 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 e
dan x
opsi diatur, maka $-
akan ada serakan huruf yang mencakup e
dan 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 x
opsi 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 builtin
kata 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 ls
untuk ls -F
, misalnya, dan bash tidak mencoba memperluas teks pengganti secara rekursif.
Tidak terlalu mengejutkan, jawaban terakhir (yang dengan echo_and_restore
) gagal jika builtin
kata kunci dihilangkan 1 . Tapi, anehnya itu berfungsi jika saya menghapus builtin
dan 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 address
pesan kesalahan, dan
- dump inti.
echo +x; echo "$*"; echo -x
dalam alias, saya ingin melihatnya.