Bagaimana cara menggunakan grep output sebagai path untuk cd?

9

Bagaimana saya bisa mem-pipe grepoutput sebagai argumen ke cdperintah?

Sebagai contoh:

[root@xxx xxx]# pip install django | grep '/usr.*'  
Requirement already satisfied (use --upgrade to upgrade): django in   /usr/lib64/python2.7/site-packages

Di sini /usr/lib64/python2.7/site-packagesdisorot dan saya ingin meneruskan string ini ke cd.

micgeronimo
sumber

Jawaban:

16

Gunakan substitusi perintah Bash $(), Anda juga perlu -odengan grep untuk hanya memilih bagian yang cocok:

cd "$(pip install django | grep -o '/usr.*')"

Perhatikan bahwa meskipun Anda akan lolos dalam kasus ini tetapi Anda harus selalu menyertakan substitusi perintah dengan tanda kutip ganda sehingga shell tidak melakukan pemisahan kata pada spasi putih (dengan ruang default, tab dan baris baru, tergantung pada IFSvariabel dalam kasus bash).

heemayl
sumber
9

Tergantung pada apa yang Anda lakukan dan tidak tahu sebelumnya tentang apa yang pipakan dihasilkan, Anda mungkin memutuskan grepuntuk sesuatu selain /usr.*.

Jika Anda tahu direktori dimulai dengan/usr (dan itu muncul di akhir garis keluaran dari pip, dan itu /usrtidak muncul di mana pun di baris sebelum nama direktori), maka itu adalah pilihan yang bagus; Jawaban heemayl memberi tahu Anda caranya.

Jika alasan Anda mengetahuinya /usradalah karena Anda baru saja menjalankan perintah dan mengetahui direktori yang ingin Anda ubah, saya sarankan solusi yang lebih sederhana untuk menjalankan perintah cd /usr/lib64/python2.7/site-packages. Ini kurang mengetik bahkan jika Anda tidak menggunakan penyelesaian tab .

Jika tidak, Anda dapat memilih regexp berbeda tergantung pada apa yang Anda ketahui tentang output yang diuraikan. Semua alternatif di bawah ini masih menganggap nama direktori muncul di akhir baris, tetapi asumsi lain bervariasi.

Jika Anda tahu nama direktori mutlak (yaitu, dimulai dengan a /) dan tidak ada yang /muncul di baris sebelum nama direktori , Anda dapat menggunakan regexp yang sama seperti pada jawaban heemayl tetapi dengan /alih - alih /usr:

cd "$(pip install django | grep -o '/.*')"

Ini cocok dengan /diikuti oleh nol atau lebih ( *) dari karakter apa pun ( .).

Jika Anda tahu nama direktori tidak mengandung spasi horisontal (tidak ada spasi atau tab) dan muncul di akhir baris , Anda dapat menggunakan:

cd "$(pip install django | grep -oP '[^\h]+$')"

Di sini saya telah menggunakan reg reg Perl ( -P) karena \hsingkatan (untuk [:blank:]) membuatnya lebih mudah untuk mengetik dan membaca daripada regexp tambahan yang setara ( -E). Ini cocok dengan satu atau lebih ( +) karakter apa pun di kelas karakter ( [ ]) yang bukan ( ^) spasi atau tab ( \h).

Jika Anda tahu bahwa nama direktori segera didahului dengan indikelilingi oleh spasi putih horisontal (yaitu, empuk di kiri dan kanan dengan kosong), dan bahwa ini adalah satu-satunya kejadian seperti inpada baris , Anda dapat menggunakan:

cd "$(pip install django | grep -oP '\hin\h+\K.+')"

Ini menggunakan pernyataan lebar-belakang positif nol-melihat ( \K) untuk mencocokkan satu atau lebih karakter ( .+) yang muncul setelah spasi atau tab ( \h) in,, dan satu atau lebih spasi atau tab lainnya ( \h+), tanpa benar-benar memasukkan indan spasi kosong mengelilinginya dalam pertandingan. Pernyataan look-around adalah fitur ekspresi reguler Perl.

Polanya akan bekerja juga, tetapi kita hanya perlu mencari satu yang kosong sebelumnya , terlepas dari berapa banyak yang hadir. Sebaliknya, kita harus mencocokkan semua kosong setelahnya , atau mereka tidak akan dibuang oleh dan mereka akan dicocokkan sebagai bagian dari nama direktori.\h+in\h+\K.+inin\K

Jika Anda tahu nama direktori segera didahului oleh kemunculan baris terakhirin diikuti oleh spasi horisontal , Anda dapat menggunakan:

set +H
cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')"
set -H

Di sana, pernyataan pandangan ke belakang nol-lebar positif itu sendiri berisi pernyataan pandangan ke depan nol-lebar negatif ( (?! )).

The !muncul dengan cara seperti sulit untuk melarikan diri elegan; metode yang saya gunakan untuk mencegahnya memicu ekspansi histori shell sebelum diteruskan ke grepadalah menonaktifkan sementara ekspansi histori ( set +H) sebelum menjalankan perintah dan mengaktifkannya kembali ( set -H) sesudahnya. Jika Anda menggunakan ini dalam skrip dan skrip Anda tidak mengandung set -H, Anda tidak perlu melakukan ini karena ekspansi riwayat diaktifkan secara otomatis hanya ketika shell berjalan secara interaktif.

Akhirnya, perhatikan bahwa tidak satu pun dari ini, atau jawaban heemayl , sebenarnya menyalurkan output grepke cd(meskipun output pipmasih disalurkan ke grep). Alih-alih pipa , alat yang tepat untuk pekerjaan ini adalah substitusi perintah .

Eliah Kagan
sumber
Tentu saja, jika Anda ingin mendapatkan teknis , shell menggunakan pipa secara internal untuk membaca output perintah.
Acak832
@ Random832 Poin bagus - Saya telah mengedit sedikit untuk pertimbangan ini. Btw, apakah Anda tahu jika penggunaan pipa "di bawah tenda" dalam substitusi perintah dapat diandalkan? Atau itu detail implementasi yang berpotensi dilakukan secara berbeda di versi bash yang berbeda di masa mendatang? (Tentu saja, dalam praktiknya, saya mengerti ini adalah cara terbaik untuk melakukannya, dan karenanya tidak mungkin diterapkan secara berbeda.)
Eliah Kagan
1
Tidak, itu tidak dijamin, secara teori shell dapat menggunakan fifo atau temp file bernama, meskipun tidak ada alasan untuk itu.
Random832
Apakah Anda yakin tentang perluasan sejarah? Satu-satunya karakter yang dapat memblokirnya adalah ` and '', dan Anda telah menggunakan tanda kutip tunggal di sekitar ekspresi grep.
muru
1
@uru Ya, itu diperluas. Saya juga tidak memperhatikan, tetapi menemukan ketika saya mengujinya. Di !sana tidak dikutip dengan '-quotes, karena '-quotes sendiri dikutip. Kompleksitas perintah membuatnya mudah untuk salah memprediksi efeknya, tetapi tampaknya karena urutan ekspansi ( !lebih awal) ia akhirnya berfungsi seperti x=foo; echo "'$x'"(-> 'foo'). Menghapus "kuota- luar akan menyebabkan !- 'dikutip dan mencegah ekspansi sejarah, tetapi kemudian cd akan gagal jika direktori memiliki spasi dalam namanya.
Eliah Kagan