Làm thế nào để tôi thực thi nhiều lệnh bằng cách sử dụng cùng một đối số?


16

Tôi tự hỏi liệu có thể thực hiện các hành động chuỗi trong thiết bị đầu cuối Ubuntu như:

action 1 on objectA . then action 2 on objectA 

mà không phải lặp lại tên của objectA nữa.

Thí dụ:

touch file.js && openEditor "$1" 

hoặc điều tương tự.


Có rất nhiều cách để làm điều đó, nhưng phụ thuộc vào nhu cầu của bạn. Đối tượng là gì? một tập tin ? Những hành động chúng ta đang nói về?
Sergiy Kolodyazhnyy

cảm ơn, thường là một tệp hiệu quả, cũng có thể là một thư mục
HoCo_

3
Ở đây, &sẽ gửi lệnh "chạm" vào nền. Nếu bạn có ý định "mở trình chỉnh sửa nếu chạm thành công", thì bạn muốn &&thay vào đó
glenn jackman

Tại sao bạn lại trả bài này? Bạn đã có rất nhiều câu trả lời và thậm chí chấp nhận một câu trả lời.
muru

Câu trả lời:


27

Với bash History Expansion , bạn có thể tham khảo từ thứ n của dòng lệnh hiện tại bằng cách sử dụng !#:neg

$ 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

Tôi có thể hỏi, phiên bản bash nào bạn đang sử dụng không?
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy đây làGNU bash, version 4.3.48(1)-release
Steeldo

5
bạn cũng có thể chỉ định một loạt các từ :touch foo bar && ls -l !#:1-2
glenn jackman

1
@HoCo_ !nhân vật giới thiệu một biểu thức mở rộng lịch sử khi bạn ở trong vỏ tương tác - nó có nghĩa là thao tác dòng lệnh khi bạn đang gõ và bị vô hiệu hóa trong các tập lệnh không tương tác
Steelepage

1
@HoCo_ trong một tập lệnh, bạn nên biết trước đối số là gì - vì vậy, ví dụ bạn chỉ có thể làmarg1=file.js; touch "$arg1" && openEditor "$arg1"
Steeldo

12

Có một phím tắt tiện dụng cho một trường hợp sử dụng phổ biến. Trong ví dụ của bạn, bạn đang làm:

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

Trong lệnh thứ hai, mẹo là viết openEditor(có khoảng trắng sau nó) theo sau là Alt+ .. Điều này sẽ chèn đối số cuối cùng của lệnh cuối cùng , đó là file.js. (Nếu nó không hoạt động với Altmột số lý do, Escthì cũng nên hoạt động.)

Vì thường "đối tượng" thực sự là đối số cuối cùng của lệnh trước đó, nên điều này có thể được sử dụng thường xuyên. Nó rất dễ nhớ và sẽ nhanh chóng tích hợp vào bộ phím tắt shell được sử dụng trực quan của bạn.

Có rất nhiều điều bạn có thể làm với điều này, đây là một bài viết chuyên sâu về các khả năng: /programming/4009412/how-to-use-argument-from-preingly-command .

Là một phần thưởng, điều này sẽ hoạt động không chỉ trong bash mà trong tất cả các chương trình sử dụng libreadline để xử lý đầu vào dòng lệnh.


2
Bạn có thể kết hợp điều này với một lý lẽ chữ số , ví dụ như để có được giữ số thứ hai Altvà nhấn 2.(hoặc Esc, 2, Esc, .), để có được lần thứ hai để tranh luận cuối cùng bấm Alt+ -, gõ 2và nhấn Alt+ .(hoặc Esc, -2, Esc, .).
tráng miệng

@dPlay Điều gì xảy ra nếu tôi chạy muốn nhiều hơn một trong các đối số? Ví dụ: tôi chạy echo 1 2 3 4thì tôi muốn 23cho lệnh tiếp theo
wjandrea

@dPlay Tìm thấy nó bản thân mình! Bạn chỉ cần gõ một cái gì đó khác giữa chúng, như một khoảng trắng. Để nối chúng, cách dễ nhất là nhập một khoảng trắng sau đó xóa lùi.
wjandrea

1
@wjandrea giữ Altvà gõ 2., nhấn phím cách, giữ Altvà gõ 3.- nếu bạn muốn một phạm vi, hãy sử dụng mở rộng lịch sử : !!:2-3.
tráng miệng

9

Theo như shell tương tác mặc định bashvà shell script dash, bạn có thể sử dụng $_để gọi lại đối số cuối cùng của lệnh cuối cùng .

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

csh và tcsh có các tham chiếu lịch sử, cụ thể cho từ cuối cùng của lệnh, bạn có thể sử dụng !$và cho các đối số riêng lẻ - !:<index>:

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

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

Nói chung, tốt hơn hết là gán bất cứ thứ gì objectAcho một biến và sử dụng nó trong nhiều lệnh, vòng lặp, v.v. Ngoài ra, một hàm có thể là một lựa chọn:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory

1
Tôi chỉ muốn chỉ ra rằng $_hoạt động hơi khác so !#:nvới cái sau được mở rộng trước khi lưu lệnh trong lịch sử. Vì vậy, quay trở lại trong lịch sử vẫn sẽ hiển thị lệnh $_trong khi !#:nsẽ được thay thế bằng giá trị thực của nó. Cả hai đều có ưu và nhược điểm của họ.
Dan

3
Ngoài ra, như thường lệ, $_nên được trích dẫn, vì nếu không nó sẽ bị chia tách và hình cầu như mọi thứ khác. (Chúng ta chỉ không thấy nó ở đây vì echotham gia vào các đối số của nó với một khoảng trắng.) Nhưng ví dụ: touch "hello there"; ls -l $_ sẽ không hoạt động.
ilkkachu

1
@ Tôi nghĩ chuyên gia lớn nhất $_là nó di động. Rốt cuộc, !#:nlà bash cụ thể.
Sergiy Kolodyazhnyy

3

Tôi muốn đề nghị chống lại cách tiếp cận lịch sử được đưa ra trong câu trả lời của Steeldo . Điều này phụ thuộc vào nhà nước toàn cầu, vốn luôn dễ vỡ.

Tốt hơn là trả trước vòng lặp trên tất cả các lệnh cần thiết, sử dụng một biến thể phù hợp:

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

Có một chút vấn đề nói chung là Bash không hủy bỏ khi có một thất bại, tức là điều này thực sự hành xử như touch foo.txt; gedit foo.txtthay vì xâu chuỗi &&. Vì vậy, để an toàn, bạn có thể thêm break:

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

1

Khi nấu một lớp lót, đôi khi tôi gán điều lặp đi lặp lại của mình cho một biến shell mà tôi sử dụng nhiều lần trong lệnh. Tôi có thể nhớ lại và chỉnh sửa nó để sử dụng một đối số khác với mũi tên lên, control + a, control + mũi tên phải để đưa con trỏ đến gần t=.

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

Lưu ý rằng điều này giúp dễ dàng xử lý một phần mở rộng hoặc một biến thể về tên.

Cũng lưu ý rằng tôi cần một ;biến sau khi gán biến, bởi vì var=value cmdchỉ đặt đó là biến môi trường cho lệnh đó và không ảnh hưởng đến bối cảnh shell.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.