ฉันจะรันคำสั่งหลายคำสั่งโดยใช้อาร์กิวเมนต์เดียวกันได้อย่างไร


16

ฉันสงสัยว่ามันเป็นไปได้ที่จะทำการกระทำลูกโซ่ใน terminal Ubuntu เช่น:

action 1 on objectA . then action 2 on objectA 

โดยไม่ต้องทำซ้ำชื่อของ objectA อีกต่อไป

ตัวอย่าง:

touch file.js && openEditor "$1" 

หรืออะไรทำนองนั้น


มีหลายวิธีที่จะทำเช่นนั้น แต่ขึ้นอยู่กับความต้องการของคุณ objectA คืออะไร ไฟล์ ? เรากำลังพูดถึงการกระทำอะไร
Sergiy Kolodyazhnyy

ขอบคุณโดยปกติไฟล์จะมีประสิทธิภาพสามารถเป็นโฟลเดอร์ได้
HoCo_

3
ที่นี่&จะส่งคำสั่ง "สัมผัส" ไปยังพื้นหลัง หากคุณตั้งใจจะ "เปิดโปรแกรมแก้ไขหากการสัมผัสสำเร็จ" คุณต้องการ&&แทน
glenn jackman

ทำไมคุณถึงกระแทกโพสต์นี้ คุณได้รับคำตอบมากมายและยอมรับแล้ว
muru

คำตอบ:


27

ด้วยการขยายประวัติ bash คุณสามารถอ้างถึงคำที่ n ของบรรทัดคำสั่งปัจจุบันโดยใช้!#:nเช่น

$ 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

ฉันขอถามได้ไหมว่าคุณใช้เวอร์ชั่นทุบตีรุ่นไหน?
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy นี่คือGNU bash, version 4.3.48(1)-release
steeldriver

5
นอกจากนี้คุณยังสามารถกำหนดคำศัพท์ได้หลายคำ :touch foo bar && ls -l !#:1-2
glenn jackman

1
@HoCo_ !ตัวละครนำเสนอนิพจน์การขยายประวัติเมื่อคุณอยู่ในเชลล์แบบโต้ตอบ - มันมีไว้สำหรับการจัดการบรรทัดคำสั่งแบบทันทีขณะที่คุณพิมพ์และถูกปิดใช้งานในสคริปต์ที่ไม่โต้ตอบ
steeldriver

1
@HoCo_ ในสคริปต์ที่คุณควรรู้ว่าการโต้เถียงล่วงหน้านั้นเป็นเช่นไรตัวอย่างเช่นคุณสามารถทำได้arg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver

12

มีทางลัดที่สะดวกสำหรับกรณีใช้งานทั่วไป ในตัวอย่างของคุณคุณกำลังทำ:

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

ในคำสั่งที่สองเคล็ดลับคือการเขียนopenEditor(ที่มีพื้นที่หลังจากที่มัน) ตามด้วย+Alt .ซึ่งจะแทรกสุดท้ายอาร์กิวเมนต์ของสุดท้ายfile.jsคำสั่งซึ่งเป็น (ถ้ามันไม่ทำงานด้วยAltเหตุผลบางอย่างEscควรทำงานเช่นกัน)

เนื่องจากบ่อยครั้งที่ "object" เป็นอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้านี้จึงสามารถใช้งานได้บ่อยครั้ง มันง่ายต่อการจดจำและจะรวมเข้ากับชุดช็อตคัทเชลล์ที่ใช้งานได้อย่างรวดเร็ว

มีทั้งกลุ่มของสิ่งที่คุณสามารถทำอะไรกับเรื่องนี้ก็คือที่นี่เป็นบทความในเชิงลึกเกี่ยวกับความเป็นไปได้: /programming/4009412/how-to-use-arguments-from-previous-command

เป็นโบนัสสิ่งนี้จะใช้ได้ไม่เฉพาะในการทุบตีเท่านั้น แต่ในทุกโปรแกรมที่ใช้ libreadline สำหรับการประมวลผลอินพุตบรรทัดคำสั่ง


2
คุณสามารถรวมนี้มีข้อโต้แย้งหลักเช่นการได้รับถืออาร์กิวเมนต์ที่สองAltและกด2.(หรือEsc, 2, Esc, .) ที่จะได้รับที่สองที่จะอาร์กิวเมนต์สุดท้ายกดAlt+ -พิมพ์2และกดAlt+ .(หรือEsc, -2, Esc, .)
ของหวาน

@dessert จะเกิดอะไรขึ้นถ้าฉันต้องการมากกว่าหนึ่งอาร์กิวเมนต์? เช่นฉันเรียกใช้echo 1 2 3 4แล้วฉันต้องการ2และ3สำหรับคำสั่งต่อไป
wjandrea

@dessert ค้นพบด้วยตัวเอง! คุณเพียงแค่ต้องพิมพ์อย่างอื่นระหว่างพวกเขาเช่นช่องว่าง ในการต่อข้อมูลเข้าด้วยกันวิธีที่ง่ายที่สุดคือการพิมพ์ช่องว่างจากนั้นย้อนกลับ
wjandrea

1
ถือ @wjandrea Altและประเภท2., แป้นกดค้างไว้Altและประเภท3.- !!:2-3ถ้าคุณต้องการช่วงการขยายตัวของประวัติศาสตร์การใช้งาน:
ของหวาน

9

เท่าที่เริ่มต้นเปลือกโต้ตอบbashและเปลือกสคริปต์dashไปคุณสามารถใช้$_ในการจำอาร์กิวเมนต์สุดท้ายของคำสั่งสุดท้าย

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

cshและ tcsh มีการอ้างอิงประวัติโดยเฉพาะสำหรับคำสุดท้ายของคำสั่งคุณสามารถใช้!$และสำหรับแต่ละอาร์กิวเมนต์ - !:<index>:

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

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

โดยทั่วไปจะเป็นการดีกว่าที่จะกำหนดสิ่งใดก็ตามobjectAให้กับตัวแปรและใช้ในหลาย ๆ คำสั่งลูป ฯลฯ หรือมิฉะนั้นฟังก์ชันอาจเป็นตัวเลือก:

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

1
ฉันแค่อยากจะชี้ให้เห็นว่าการ$_ทำงานแตกต่างเล็กน้อยกว่า!#:nที่ขยายหลังก่อนบันทึกคำสั่งในประวัติศาสตร์ ดังนั้นการย้อนกลับไปในประวัติศาสตร์จะยังคงแสดงคำสั่งด้วย$_ขณะที่!#:nจะถูกแทนที่ด้วยค่าจริง ทั้งสองมีข้อดีและข้อเสีย
Dan

3
นอกจากนี้ตามปกติ$_ควรจะยกมาเป็นอย่างอื่นมันจะได้รับการแยกและกลมเหมือนทุกอย่างอื่น (เราแค่ไม่เห็นที่นี่ตั้งแต่echoเข้าร่วมการโต้แย้งด้วยช่องว่างเดียว) แต่เช่นtouch "hello there"; ls -l $_ จะไม่ทำงาน
ilkkachu

1
@ ฉันคิดว่าโปรที่ใหญ่ที่สุด$_คือมันพกพาได้ หลังจากทั้งหมด!#:nเป็นทุบตีเฉพาะ
Sergiy Kolodyazhnyy

3

ฉันจะแนะนำวิธีการกับประวัติศาสตร์ที่กำหนดในคำตอบของ steeldriver สิ่งนี้ต้องอาศัยสภาพโลกซึ่งเปราะบางอยู่เสมอ

ดีกว่าคือการวนรอบล่วงหน้าเหนือคำสั่งที่จำเป็นทั้งหมดโดยใช้ตัวแปรที่เหมาะสม:

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

สิ่งที่เป็นบิตของปัญหาโดยทั่วไปคือการที่ทุบตีไม่ยกเลิกเมื่อมีความล้มเหลวเช่นนี้จริงพฤติกรรมเช่นแทนที่จะผูกมัดกับtouch foo.txt; gedit foo.txt &&ดังนั้นเพื่อความปลอดภัยคุณสามารถเพิ่มbreak:

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

1

เมื่อปรุงอาหารแบบหนึ่งซับบางครั้งฉันกำหนดสิ่งที่ทำซ้ำของฉันให้กับตัวแปรเชลล์ซึ่งฉันใช้หลายครั้งในคำสั่ง ฉันสามารถจำและแก้ไขมันใช้หาเรื่องที่แตกต่างกับลูกศรขึ้นควบคุม + การควบคุม + t=ลูกศรขวาเพื่อจะได้ใกล้ชิดเคอร์เซอร์ไปที่

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

โปรดทราบว่าสิ่งนี้ทำให้ง่ายต่อการแทร็กส่วนขยายหรือรูปแบบชื่อ

นอกจากนี้โปรดทราบว่าฉันต้องการ;การกำหนดตัวแปรหลังจากเพราะvar=value cmdเพียงแค่ตั้งค่าให้เป็นตัวแปรสภาพแวดล้อมสำหรับคำสั่งนั้นและจะไม่ส่งผลกระทบต่อบริบทของเชลล์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.