Bash 4.2 pada CentOS 6.5:
Di saya, ~/.bash_profile
saya punya banyak alias, termasuk:
alias grep='grep -n --color=always'
sehingga saya bisa mendapatkan penyorotan warna dan mencetak nomor garis secara otomatis saat berjalan grep
. Jika saya menjalankan yang berikut ini, menyoroti berfungsi seperti yang diharapkan:
$ grep -Re 'regex_here' *.py
Namun, ketika saya menjalankan ini baru-baru ini:
$ find . -name '*.py' | xargs grep -E 'regex_here'
hasilnya tidak disorot dan nomor baris tidak dicetak, memaksa saya untuk kembali dan secara eksplisit menambahkan -n --color=always
ke grep
perintah.
- Tidak
xargs
membaca alias di lingkungan? - Jika tidak, adakah cara untuk membuatnya melakukannya?
xargs
perintah. Yang saya coba cari tahu adalah apakah ada cara agar saya dapat langsung memanggil alias sayaxargs
.export GREP_OPTIONS='-n --color=always'
sebelum perintah xargs Anda?.bash_profile
. Jangan ragu untuk menulis jawaban ...Jawaban:
Alias adalah internal ke shell di mana ia didefinisikan. Itu tidak terlihat oleh proses lain. Hal yang sama berlaku untuk fungsi shell.
xargs
adalah aplikasi terpisah, yang bukan shell, jadi tidak memiliki konsep alias atau fungsi.Anda dapat membuat xargs meminta shell alih-alih memohon
grep
secara langsung. Namun, menjalankan shell saja tidak cukup, Anda harus mendefinisikan alias di shell itu juga. Jika alias didefinisikan di Anda.bashrc
, Anda dapat sumber file itu; namun ini mungkin tidak berfungsi saat Anda.bashrc
melakukan tugas lain yang tidak masuk akal di shell non-interaktif.Waspadalah terhadap seluk-beluk kutipan bersarang saat mengetik regexp. Anda dapat menyederhanakan hidup Anda dengan melewatkan regexp sebagai parameter ke shell.
Anda dapat melakukan pencarian alias secara eksplisit. Maka
xargs
akan melihatgrep -n --color=always
.Dalam zsh:
By the way, perhatikan bahwa
find … | xargs …
pecah pada nama file yang mengandung spasi (antara lain) . Anda dapat memperbaikinya dengan mengubah catatan yang tidak dibatasi:atau dengan menggunakan
-exec
:Alih-alih menelepon
find
, Anda dapat melakukan semuanya di dalam shell. Pola gumpal**/
melintasi direktori secara rekursif. Di bash, Anda harus menjalankanshopt -s globstar
untuk mengaktifkan pola gumpalan ini terlebih dahulu.Ini memiliki beberapa keterbatasan:
**/
berulang menjadi tautan simbolis ke direktori.Pendekatan lain adalah dengan menggunakan substitusi proses, seperti yang disarankan oleh MariusMatutiae .
Ini berguna ketika
**/
tidak berlaku: untukfind
ekspresi kompleks , atau dalam bash ≤4.2 ketika Anda tidak ingin berulang di bawah tautan simbolis. Perhatikan bahwa ini memecah nama file yang berisi spasi; solusinya adalah mengaturIFS
dan menonaktifkan globbing , tapi itu mulai menjadi sedikit rumit:sumber
Menggunakan
alias xargs='xargs '
sumber
sudo
...Silakan anggap ini sebagai demonstrasi dari pendekatan lain, yang tidak dapat saya temukan dalam pertanyaan SO terkait :
Anda dapat menulis fungsi pembungkus
xargs
yang memeriksa apakah argumen pertama adalah alias dan jika demikian, perluaslah.Berikut ini adalah kode yang melakukan hal itu, tetapi sayangnya ia membutuhkan shell Z dan karenanya tidak menjalankan 1: 1 dengan bash (dan terus terang, saya tidak terbiasa dengan bash cukup untuk port itu):
Bukti, bahwa itu bekerja:
sumber
Solusi yang lebih sederhana, dan lebih elegan, adalah dengan menggunakan substitusi proses :
Itu tidak membuat shell baru seperti pipa, yang berarti Anda masih di shell asli Anda di mana alias didefinisikan, dan output persis seperti yang Anda inginkan.
Berhati-hatilah untuk tidak meninggalkan ruang antara pengalihan dan tanda kurung, jika tidak bash akan membuat kesalahan. Sejauh yang saya ketahui, proses substitusi didukung oleh Bash, Zsh, Ksh {88,93}, tetapi tidak oleh pdksh (saya diberitahu bahwa seharusnya belum ).
sumber
find
perintah yang kompleks , meskipun Anda harus berhati-hati bahwa itu akan merusak ruang, dan itu tidak dapat diperbaiki semudah yangfind | xargs
bisa dilakukan (dengan beralih ke-print0
dan-0
, atau menggunakan-exec
). Ketika berlaku,**/
lebih sederhana dan lebih kuat.grep akan membaca serangkaian opsi default dari variabel lingkungan GREP_OPTIONS. Jika Anda mau
di .bashrc Anda maka variabel akan diteruskan ke subshell dan Anda akan mendapatkan hasil yang Anda harapkan.
sumber
--line-number
atau--color=always
diGREP_OPTIONS
kecuali itu hanya untuk satu perintah, ini akan mematahkan banyak script.--color=auto
boleh saja ada di sana, dan itu saja. Menempatkan baris ini di Anda.bashrc
akan merusak banyak hal./etc/init.d/cron
pada sistem saya:value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2`
. Atau dari/usr/bin/pdfjam
:pdftitl=`printf "%s" "$PDFinfo" | grep -e … | sed -e …`
. Alias bukan masalah karena tidak terlihat di skrip.GREP_OPTIONS
jeda diprediksi sangat buruk, kecuali untuk beberapa opsi seperti--color=auto
(yang dirancang untuk apa).