Bagaimana cara menjalankan beberapa perintah menggunakan argumen yang sama?

16

Saya bertanya-tanya apakah mungkin untuk membuat tindakan berantai di terminal Ubuntu seperti:

action 1 on objectA . then action 2 on objectA 

tanpa harus mengulangi nama objectA lagi.

Contoh:

touch file.js && openEditor "$1" 

atau semacam itu.

HoCo_
sumber
Ada banyak cara untuk melakukan itu, tetapi tergantung pada kebutuhan Anda. Apa objekA? file ? Tindakan apa yang sedang kita bicarakan?
Sergiy Kolodyazhnyy
terima kasih, biasanya file secara efektif, juga bisa menjadi folder
HoCo_
3
Di sini, &akan mengirim perintah "sentuh" ​​ke latar belakang. Jika Anda bermaksud "membuka editor jika sentuhan berhasil", maka Anda ingin &&sebaliknya
glenn Jackman
Mengapa Anda membenturkan posting ini? Anda sudah mendapat banyak jawaban dan bahkan menerimanya.
muru

Jawaban:

27

Dengan bash History Expansion , Anda dapat merujuk kata ke-n dari baris perintah saat ini menggunakan !#:nmis

$ touch foobar && ls -l !#:1
touch foobar && ls -l foobar
-rw-rw---- 1 steeldriver steeldriver 0 Jun 20 14:54 foobar

$ touch foo bar && ls -l !#:2
touch foo bar && ls -l bar
-rw-rw-r-- 1 steeldriver steeldriver 12 Jun 20 14:58 bar
Steeldriver
sumber
Bolehkah saya bertanya, versi bash mana yang Anda gunakan?
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy iniGNU bash, version 4.3.48(1)-release
steeldriver
5
Anda juga dapat menetapkan berbagai kata :touch foo bar && ls -l !#:1-2
glenn jackman
1
@HoCo_ !karakter memperkenalkan ekspresi ekspansi sejarah ketika Anda berada di shell interaktif - itu dimaksudkan untuk manipulasi baris perintah saat Anda mengetik, dan dinonaktifkan di dalam skrip non-interaktif
steeldriver
1
@HoCo_ dalam skrip Anda harus tahu apa argumennya sebelumnya - jadi misalnya Anda bisa melakukannyaarg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver
12

Ada pintasan praktis untuk kasus penggunaan umum. Dalam contoh Anda, Anda melakukan:

$ touch file.js
$ openEditor <alt>+<.>

Pada perintah kedua, triknya adalah menulis openEditor(dengan spasi setelahnya) diikuti oleh Alt+ .. Ini akan menyisipkan argumen terakhir dari perintah terakhir , yaitu file.js. (Jika itu tidak berhasil dengan Altalasan tertentu, Escharus bekerja juga.)

Karena sering "objek" memang argumen terakhir dari perintah sebelumnya, ini dapat sering digunakan. Mudah diingat dan akan dengan cepat berintegrasi ke dalam set pintas shell yang digunakan secara intuitif.

Ada banyak hal yang dapat Anda lakukan dengan ini, berikut ini adalah artikel mendalam tentang kemungkinan: /programming/4009412/how-to-use-arguments-from-previous-command .

Sebagai bonus, ini tidak hanya bekerja di bash tetapi di semua program yang menggunakan libreadline untuk memproses input baris perintah.

Sebastian Stark
sumber
2
Anda dapat menggabungkan ini dengan argumen digit , misalnya untuk mendapatkan pegangan argumen kedua Altdan tekan 2.(atau Esc, 2, Esc, .), untuk mendapatkan kedua argumen terakhir tekan Alt+ -, jenis 2dan tekan Alt+ .(atau Esc, -2, Esc, .).
hidangan penutup
@dabut Bagaimana jika saya ingin menjalankan lebih dari satu argumen? Misal saya jalankan echo 1 2 3 4maka saya mau 2dan 3untuk perintah selanjutnya
wjandrea
@Dapatkan menemukannya sendiri! Anda hanya perlu mengetik sesuatu yang lain di antara mereka, seperti spasi. Untuk menyatukan mereka, cara termudah adalah mengetikkan ruang lalu mundur.
wjandrea
1
@wjandrea terus Altdan jenis 2., tekan spacebar, terus Altdan jenis 3.- jika Anda ingin suatu range, penggunaan ekspansi sejarah: !!:2-3.
hidangan penutup
9

Sejauh shell interaktif default bashdan shell skrip dashberjalan, Anda dapat menggunakan $_untuk mengingat argumen terakhir dari perintah terakhir .

$ echo "Hello World"; echo same "$_"
Hello World
same Hello World

csh dan tcsh memiliki referensi sejarah, khusus untuk kata terakhir dari perintah, yang dapat Anda gunakan !$, dan untuk argumen individual - !:<index>:

~% echo foo bar
foo bar
~% echo !$
echo bar
bar

% echo bar baz
bar baz
% echo !:1
echo bar
bar

Secara umum, hanya lebih baik untuk menetapkan apa pun objectAuntuk variabel, dan menggunakannya dalam banyak perintah, loop, dll. Atau, fungsi bisa menjadi pilihan:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory
Sergiy Kolodyazhnyy
sumber
1
Saya hanya ingin menunjukkan bahwa itu $_bekerja sedikit berbeda dari !#:nyang terakhir diperluas sebelum menyimpan perintah dalam sejarah. Jadi kembali dalam sejarah masih akan menunjukkan perintah dengan $_sementara !#:nakan digantikan dengan nilai aktualnya. Keduanya memiliki pro dan kontra.
Dan
3
Juga, seperti biasa, $_harus dikutip, karena jika tidak maka akan terbelah dan menggumpal seperti yang lainnya. (Kami hanya tidak melihatnya di sini karena echobergabung dengan argumennya dengan satu spasi.) Tetapi misalnya touch "hello there"; ls -l $_ tidak akan berhasil.
ilkkachu
1
@ Dan saya pikir pro terbesar $_adalah portabel. Bagaimanapun, !#:nini spesifik untuk bash.
Sergiy Kolodyazhnyy
3

Saya akan merekomendasikan menentang pendekatan sejarah yang diberikan dalam jawaban steeldriver . Ini bergantung pada negara global, yang selalu rapuh.

Lebih baik adalah mem-upfront loop semua perintah yang dibutuhkan, menggunakan variabel yang tepat:

$ for c in touch gedit; do $c foo.txt; done

Apa yang agak menjadi masalah secara umum adalah bahwa Bash tidak batal ketika ada kegagalan, yaitu ini sebenarnya berperilaku seperti touch foo.txt; gedit foo.txtbukan dengan rantai &&. Jadi, agar aman Anda dapat menambahkan break:

$ for c in touch gedit; do $c foo.txt || break; done
leftaroundabout
sumber
1

Saat memasak satu-liner, saya kadang-kadang menetapkan hal yang saya ulangi ke variabel shell yang saya gunakan beberapa kali dalam perintah. Saya dapat mengingat dan mengeditnya untuk menggunakan arg yang berbeda dengan panah atas, kontrol + a, kontrol + panah kanan untuk mendapatkan kursor dekat dengan t=.

t=testloop; asm-link -d "$t.asm" && perf stat -r2 ./"$t"

Perhatikan bahwa ini memudahkan untuk menempel pada ekstensi, atau variasi pada nama.

Juga perhatikan bahwa saya memerlukan tugas ;setelah variabel, karena var=value cmdhanya menetapkan itu sebagai variabel lingkungan untuk perintah itu, dan tidak mempengaruhi konteks shell.

Peter Cordes
sumber