Ketika kode status tidak berguna, apakah ada cara untuk membangun pipa berdasarkan output dari stdout?
Saya lebih suka jawabannya tidak membahas use-case tetapi pertanyaan dalam lingkup scripting shell. Apa yang saya coba lakukan adalah menemukan paket paling spesifik yang tersedia di repositori dengan menebak nama berdasarkan kode negara dan bahasa.
Ambil contoh ini,
$PACKAGE1=hunspell-en-zz
$PACKAGE2=hunspell-en
Tebakan pertama lebih tepat tetapi mungkin tidak ada. Dalam hal ini, saya ingin kembali hunspell-en
( $PACKAGE2
) karena opsi pertama hunspell-en-zz
( $PACKAGE1
) tidak ada.
jalur pipa apt-cache
Perintah apt-cache
mengembalikan kesuksesan (yang didefinisikan oleh shell sebagai kode keluar nol) setiap kali perintah dapat dijalankan (dari dokumen apt-cache
)
apt-cache mengembalikan nol pada operasi normal, 100 desimal pada kesalahan.
Itu membuat menggunakan perintah dalam pipa lebih sulit. Biasanya, saya mengharapkan pencarian paket setara dengan 404 untuk menghasilkan kesalahan (seperti yang akan terjadi dengan curl
atau wget
). Saya ingin mencari untuk melihat apakah ada paket, dan jika tidak kembali ke paket lain jika ada .
Ini tidak menghasilkan apa-apa, karena perintah pertama mengembalikan kesuksesan (jadi rhs dalam yang ||
tidak pernah berjalan)
apt-cache search hunspell-en-zz || apt-cache search hunspell-en
apt-cache search
dengan dua argumen
Ini tidak menghasilkan apa-apa, seperti apt-cache
argumen ANDs,
apt-cache search hunspell-en-zz hunspell-en
Dari dokumen apt-cache
Argumen terpisah dapat digunakan untuk menentukan beberapa pola pencarian yang and'ed bersama.
Jadi karena salah satu argumen itu jelas tidak ada, ini tidak menghasilkan apa-apa.
Pertanyaan
Apa idiom shell untuk menangani konvensi seperti yang ditemukan di apt-cache
mana kode kembali tidak berguna untuk tugas itu? Dan kesuksesan hanya ditentukan oleh kehadiran output pada STDOUT?
Mirip dengan
membuat menemukan gagal ketika tidak ada yang ditemukan
mereka berdua berasal dari masalah yang sama. Jawaban yang dipilih di sana menyebutkan
find -z
solusi mana yang sayangnya tidak dapat diterapkan di sini dan khusus untuk kasus penggunaan. Tidak ada penyebutan idiom atau membangun pipa tanpa menggunakan null-termination (bukan opsi aktifapt-cache
)
sumber
hunspell-en
ada? Bagaimanapun, Anda dapat menggunakanapt-cache policy
dan menerima^$PACKAGENAME:
.hunspell-ar
memang ada dan tidak ada paket nama negara. Saya perlu menemukan paket paling akurat untuk negara dan bahasa tertentu.find
sama sepertiapt-cache
dalam hal ini - kode pengembalian tidak berguna, kesuksesan didasarkan pada output.-z
yang sayangnya bukan solusi di sini sehingga masalah penggunaan-spesifik kasus tidak berlaku. Dan tidak ada penyebutan idiom atau membangun saluran pipa tanpa menggunakan null-termination (bukan opsi padaapt-cache
)find
untuk digunakan-print0
dan jadi mengerti-z
. Karena apt-cache tidak memberikan keluaran yang diakhiri null, Anda tidak perlu-z
.Jawaban:
Buat fungsi yang mengambil perintah dan mengembalikan true jika memiliki beberapa output.
Jadi untuk kasus penggunaan ini akan berfungsi seperti ini,
sumber
r printf '\n\n\n'
akan kembali salah. Dengan kerang selainzsh
,r printf '\0\0\0'
juga akan kembali palsu. Begitu jugar printf '\0a\0b\0c'
dengan beberapa kerang.Sejauh yang saya tahu, tidak ada cara standar untuk menangani kasus-kasus di mana keberhasilan suatu perintah ditentukan oleh kehadiran output. Anda bisa menulis solusinya.
Misalnya, Anda dapat menyimpan output dari perintah dalam variabel dan kemudian memeriksa apakah variabel itu kosong atau tidak:
Saya pikir ini menjawab pertanyaan secara umum, tetapi jika kita berbicara tentang
apt-cache search
beberapa solusi datang ke pikiran saya.Saya memiliki skrip yang membuat manajemen paket lebih mudah. Beberapa fungsinya adalah sebagai berikut:
Ini memungkinkan Anda untuk melakukan beberapa pencarian dalam satu perintah. Sebagai contoh:
Setiap fungsi mencari database dengan cara yang berbeda, sehingga hasilnya dapat bervariasi tergantung pada fungsi yang Anda gunakan:
sumber
Saya tidak akan menyebut ini anggun, tetapi saya pikir ini mungkin berhasil:
Sayangnya saya tidak memiliki mesin debian untuk diuji. Saya telah menyertakan opsi
-n
untuk "hanya nama"apt-cache
untuk mencoba dan membatasi hasil pencarian karena sepertinya Anda sebagian besar yakin dengan apa yang Anda cari.Dapat dijalankan seperti:
sumber
-q
opsi yang sepi? Halaman manual tidak terlalu bertele-tele tentang itu tetapi mungkin itu mengubah nilai kembali?Muru menjelaskan ini dalam komentar
grep
akan mengembalikan status 1 jika tidak ada input. Jadi Anda dapat menambahkangrep .
ke aliran dan jika tidak ada input yang cocok dengan pola.
, itu akan mengubah kode status:Untuk kasus penggunaan yang terlihat seperti ini. Di bawah ini, tidak ada
-pl-pl
sehingga jatuh kembali dan kembalihunspell-pl
Atau,
Ada
-en-US
sehingga kembalihunspell-en-us
.Lihat juga,
sumber
grep .
mengembalikan true jika input mengandung setidaknya satu (dibatasi sepenuhnya dengan beberapa implementasi) baris yang berisi setidaknya satu (terbentuk dengan sebagian besar implementasi) karakter dan jika tidak akan menghapus baris kosong.grep '^'
akan bekerja lebih baik untuk memeriksa bahwa ada beberapa output, meskipun dengan beberapa implementasi masih bisa mengembalikan false jika input adalah satu baris yang tidak dibatasi (dan dapat menghapus baris itu, atau dengan implementasi lain, mengembalikan nilai true tetapi menambahkan baris baru yang hilang). Beberapa implementasi grep juga mencekik karakter NUL.Anda dapat mendefinisikan:
Lalu:
Beberapa
awk
implementasi mungkin tersedak karakter NUL dalam input.Bertentangan dengan itu
grep '^'
, di atas akan dijamin bekerja pada input yang tidak berakhir pada karakter baris baru, tetapi akan menambahkan baris baru yang hilang.Untuk menghindari itu dan menjadi portabel untuk sistem di mana
awk
tersedak NUL, Anda bisa menggunakanperl
:Dengan
perl
, Anda juga bisa menentukan varian yang menangani file sewenang-wenang dengan lebih anggun:Itu membatasi penggunaan memori (seperti untuk file yang tidak memiliki karakter baris baru seperti file jarang besar).
Anda juga dapat membuat varian seperti:
atau:
(berhati-hatilah definisi blank bervariasi antara
awk
implementasi, beberapa di mana terbatas pada ruang dan tab, beberapa di mana juga termasuk karakter spasi vertikal ASCII seperti CR atau FF, beberapa di mana ia menganggap kosong lokal)Idealnya, di Linux, Anda ingin menggunakan
splice()
panggilan sistem untuk memaksimalkan kinerja. Saya tidak tahu dari perintah yang akan memaparkannya tetapi Anda selalu bisa menggunakanpython
'sctypes
:(perhatikan bahwa baik
has_output
stdin atau stdout (atau keduanya) harus menjadi pipa untuksplice()
bekerja).sumber
Saya akan menyarankan untuk menggunakan fungsi builtin yang sangat dasar dari shell:
Ini adalah contoh uji paling sederhana:
Maka Anda dapat dengan mudah menggunakannya dengan
||
konstruk yang biasa Anda gunakan:Fungsi sederhana ini akan berfungsi seperti yang Anda inginkan dengan
apt_cache
perilaku Anda , berapa pun jumlah argumennya.sumber
ck_command echo 'asdf' | cat
tidak menghasilkan apa-apa.