Saya memiliki skrip yang cukup sederhana yaitu seperti berikut:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Ketika saya menjalankan skrip ini dari baris perintah dan memberikan argumen, saya tidak mendapatkan hasil apa pun. Namun, ketika saya menjalankan perintah yang terkandung dalam $MOREF
variabel, saya bisa mendapatkan output.
Bagaimana seseorang dapat mengambil hasil dari perintah yang perlu dijalankan dalam skrip, menyimpannya ke variabel, dan kemudian menampilkan variabel itu di layar?
bash
shell
command-line
John
sumber
sumber
echo
menggunakan variabel tersebut sebagai penggunaan yang tidak bergunaecho
, dan penggunaan variabel yang tidak berguna.Jawaban:
Selain backticks
`command`
, substitusi perintah dapat dilakukan dengan$(command)
atau"$(command)"
, yang menurut saya lebih mudah dibaca, dan memungkinkan untuk bersarang.Mengutip (
"
) penting untuk mempertahankan nilai variabel multi-line ; ini opsional di sisi kanan tugas, karena pemisahan kata tidak dilakukan , jadiOUTPUT=$(ls -1)
akan berfungsi dengan baik.sumber
echo
perintah.${OUTPUT}foo
. Mereka juga diperlukan saat melakukan operasi string sebaris pada variabel, seperti${OUTPUT/foo/bar}
Cara yang benar adalah
Jika Anda akan menggunakan tanda kutip, Anda perlu
`
, tidak'
. Karakter ini disebut "backticks" (atau "aksen kubur").Seperti ini:
sumber
echo
.$()
bekerja. Tidak dapat memperbaiki sampai saya melihat halaman ini.Beberapa trik Bash yang saya gunakan untuk mengatur variabel dari perintah
Sunting ke-2 2018-02-12: Menambahkan cara yang berbeda, cari di bagian bawah ini untuk tugas yang sudah berjalan lama !
Edit 2018-01-25: menambahkan fungsi sampel (untuk mengisi variabel tentang penggunaan disk)
Pertama sederhana, lama, dan cara yang kompatibel
Paling kompatibel, cara kedua
Karena bersarang bisa menjadi berat, kurung diimplementasikan untuk ini
Sampel bersarang:
Membaca lebih dari satu variabel (dengan Bashisms )
Jika saya hanya ingin nilai yang digunakan :
Anda bisa melihat variabel array :
Kemudian:
Tapi saya lebih suka ini:
Yang pertama
read foo
hanya akan melewati baris tajuk, tetapi hanya dalam satu perintah, Anda akan mengisi 7 variabel yang berbeda :Atau bahkan:
... akan bekerja dengan array asosiatif juga:
read foo disk[total] disk[used] ...
Fungsi sampel untuk mengisi beberapa variabel:
Catatan:
declare
baris tidak diperlukan, hanya agar mudah dibaca.Tentang
sudo cmd | grep ... | cut ...
(Tolong hindari yang tidak berguna
cat
! Jadi ini hanya satu fork less:Semua pipa (
|
) menyiratkan garpu. Di mana proses lain harus dijalankan, mengakses disk, pustaka panggilan, dan sebagainya.Jadi gunakan
sed
untuk sampel, akan membatasi subproses hanya satu garpu :Dan dengan Bashisme :
Tetapi untuk banyak tindakan, kebanyakan pada file kecil, Bash dapat melakukan pekerjaan itu sendiri:
atau
Lebih jauh tentang pemisahan variabel ...
Lihat jawaban saya untuk Bagaimana cara membagi string pada pembatas di Bash?
Alternatif: mengurangi garpu dengan menggunakan tugas yang sudah berjalan di latar belakang
Edit ke-2 2018-02-12:
Untuk mencegah beberapa garpu suka
atau
Ini berfungsi dengan baik, tetapi menjalankan banyak garpu berat dan lambat.
Dan perintah suka
date
danbc
bisa membuat banyak operasi, baris demi baris !!Lihat:
Jadi kami dapat menggunakan proses latar belakang yang berjalan lama untuk membuat banyak pekerjaan, tanpa harus memulai garpu baru untuk setiap permintaan.
Kami hanya perlu beberapa deskriptor dan fifos file untuk melakukan ini dengan benar:
(Tentu saja, FD
5
dan6
harus tidak digunakan!) ... Dari sana, Anda dapat menggunakan proses ini dengan:Menjadi suatu fungsi
newConnector
Anda dapat menemukan
newConnector
fungsi saya di GitHub.Com atau di situs saya sendiri (Catatan tentang GitHub: ada dua file di situs saya. Fungsi dan demo digabungkan menjadi satu file yang dapat bersumber untuk digunakan atau hanya dijalankan untuk demo.)Sampel:
Fungsi ini
myBc
memungkinkan Anda menggunakan tugas latar belakang dengan sintaks sederhana, dan untuk tanggal:Dari sana, jika Anda ingin mengakhiri salah satu proses latar belakang, Anda hanya perlu menutup fd :
yang tidak diperlukan, karena semua fd tutup ketika proses utama selesai.
sumber
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
adalah pernyataan yang saya cari.echo
; Anda hanya ingingrep "$CONTAINER_NAME"
tput
ini menggunakan sebagai tugas latar belakang untuk rendering warna pada terminal !!kubectl get ns | while read -r line; do echo
$ line | grep Term | cut -d '' -f1; done
mencetak untuk setiap$line
baris kosong dan kemudianbash: xxxx: command not found
. Namun saya akan berharap bahwa itu hanya mencetakxxx
Seperti yang telah ditunjukkan kepada Anda, Anda harus menggunakan 'backticks'.
Alternatif yang diusulkan juga
$(command)
berfungsi, dan juga lebih mudah dibaca, tetapi perhatikan bahwa itu hanya valid dengan Bash atau KornShell (dan cangkang yang berasal dari itu), jadi jika skrip Anda harus benar-benar portabel pada berbagai sistem Unix, Anda sebaiknya memilih notasi backticks yang lama.sumber
$()
sepenuhnya kompatibel dengan POSIX sh, seperti yang distandarisasi lebih dari dua dekade lalu./bin/sh
pada Solaris 10 masih tidak mengenali$(…)
- dan AFAIK juga berlaku pada Solaris 11./bin/sh
adalahksh93
.$()
POSIX shell di HP-UX selama 10+ tahun terakhir.Saya tahu tiga cara untuk melakukannya:
Fungsinya sesuai untuk tugas-tugas tersebut: **
Pinta dengan mengatakan
func
.Juga solusi lain yang cocok bisa berupa eval:
Yang ketiga menggunakan variabel secara langsung:
Anda bisa mendapatkan output dari solusi ketiga dengan cara yang baik:
Dan juga dengan cara yang jahat:
sumber
"$var"
baik dan$var
jahat?Hanya untuk berbeda:
sumber
Saat mengatur variabel, pastikan Anda memiliki NO Spaces sebelum dan / atau setelah tanda = . Secara harfiah menghabiskan satu jam mencoba untuk mencari tahu ini, mencoba semua jenis solusi! Ini tidak keren.
Benar:
Akan Gagal dengan kesalahan "barang: tidak ditemukan" atau serupa
sumber
var=value somecommand
berjalansomecommand
denganvar
lingkungannya yang memiliki nilaivalue
. Dengan demikian,var= somecommand
mengeksporvar
dalam lingkungansomecommand
dengan nilai kosong (nol-byte).Jika Anda ingin melakukannya dengan multiline / beberapa perintah / s maka Anda dapat melakukan ini:
Atau:
Contoh:
Keluaran:
Dengan menggunakan heredoc , Anda dapat menyederhanakan banyak hal dengan mudah dengan memecah kode baris tunggal panjang Anda menjadi multiline. Contoh lain:
sumber
bash
di dalam substitusi perintah? Anda sudah membuat subkulit dengan substitusi perintah itu sendiri. Jika Anda ingin menempatkan beberapa perintah, cukup pisahkan dengan baris baru atau titik koma.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
akan "berbeda", juga; tapi saya tidak mengerti intinya.ssh
sudo -s
mengeksekusi perintah mysql di dalam, dll. (Bukan bash)variable=$(bash -c 'echo "foo"; echo "bar"')
lebihvariable=$(echo "foo"; echo "bar")
- di sini dokumen hanya mekanisme mengutip dan tidak benar-benar menambahkan apa-apa kecuali komplikasi tidak berguna lagi.ssh -p $port $user@$domain /bin/bash <<EOF
untuk mencegahPseudo-terminal will not be allocated because stdin is not a terminal.
peringatanAnda harus menggunakan keduanya
$(command-here)
atau
Contoh
sumber
$()
jauh lebih baik daripada backticks. Lihat: Apa manfaat menggunakan $ () daripada backtick dalam skrip shell?Ini adalah cara lain dan baik untuk digunakan dengan beberapa editor teks yang tidak dapat menyorot dengan benar setiap kode rumit yang Anda buat:
sumber
Anda dapat menggunakan backticks (juga dikenal sebagai aksen kuburan) atau
$()
.Suka:
Keduanya memiliki efek yang sama. Tetapi OUTPUT = $ (x + 2) lebih mudah dibaca dan yang terbaru.
sumber
Jika perintah yang Anda coba jalankan gagal, itu akan menulis output ke aliran kesalahan dan kemudian akan dicetak ke konsol.
Untuk menghindarinya, Anda harus mengarahkan aliran kesalahan:
sumber
Beberapa mungkin menemukan ini berguna. Nilai integer dalam substitusi variabel, di mana triknya menggunakan
$(())
tanda kurung ganda:sumber
for ((...))
loop akan terlihat lebih cocok untuk variabel loop) ). Selain itu, Anda tidak boleh menggunakan huruf besar untuk variabel pribadi Anda.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
tetapi saya setuju dengan @tripleee: Saya tidak mengerti apa yang dilakukan, ini!Berikut ini dua cara lagi:
Harap diingat bahwa ruang sangat penting di Bash. Jadi, jika Anda ingin perintah Anda dijalankan, gunakan apa adanya tanpa memasukkan spasi lagi.
Berikut ini menetapkan
harshil
untukL
dan mencetaknyaBerikut ini memberikan output dari perintah
tr
ke L2.tr
sedang dioperasikan pada variabel lain, L1.sumber
$"..."
mungkin tidak melakukan apa yang Anda pikirkan . 2. Ini sudah diberikan dalam jawaban Andy Lester.echo ${L1,,}
untuk menurunkan, atauecho ${L1^^}
untuk menghapus.