ฉันสามารถส่งอาร์กิวเมนต์ไปยังคำสั่ง alias ได้หรือไม่?


19

ฉันต้องการทราบว่าฉันสามารถส่งผ่านข้อโต้แย้งด้วยคำสั่งนามแฝง

ตัวอย่างเช่น:

alias d="dmesg|grep -iw usb|tail -5" 

ตอนนี้dจะพิมพ์ 5 บรรทัดสุดท้าย หากฉันต้องการใช้ d เพื่อพิมพ์จำนวนบรรทัดที่แตกต่างกันฉันต้องทำการเปลี่ยนแปลงในการประกาศคำสั่ง alias dอีกครั้ง

มีวิธีใดบ้างที่ฉันสามารถแก้ไขการประกาศของนามแฝงเพื่อที่ฉันจะได้ไม่ต้องพิมพ์การประกาศซ้ำเพื่อเปลี่ยนจำนวนบรรทัด เช่นเดียวกับการใช้มาตรการที่ผ่านจำนวนของสายเป็นอาร์กิวเมนต์ในขณะที่การประกาศนามแฝงสำหรับd? หรือมีวิธีอื่นในการแก้ปัญหานี้?


ใน (t) csh, "\! *" อ้างอิงอาร์กิวเมนต์ไปยังนามแฝง (เครื่องหมายแบ็กสแลชเป็นเพียงการหลบหนีเครื่องหมายอัศเจรีย์ซึ่งโดยปกติหมายถึง "ประวัติ") และคุณยังสามารถอ้างอิงอาร์กิวเมนต์แต่ละตัวได้แม้ว่าฉันจะจำไม่ได้ว่าอย่างไร ดังนั้นบางที "tail -n \! *" หรืออะไรบางอย่าง (ฉันไม่คิดว่า \! * จะทำงานกับเครื่องหมายลบทันทีก่อนหน้านั้น) อย่างไรก็ตามไม่แน่ใจว่าจะทำงานใน (ba) sh หรือไม่
barrycarter

คำตอบ:


20

นามแฝงไม่รับข้อโต้แย้ง ด้วยนามแฝงชอบalias foo='bar $1'ที่$1จะได้รับการขยายตัวเปลือกเพื่ออาร์กิวเมนต์แรกของเปลือก (ซึ่งมีแนวโน้มว่าอะไร) เมื่อนามแฝงเป็นระยะ

ดังนั้น: ใช้ฟังก์ชั่นแทน

d () {
  num=${1:-5}
  dmesg |grep -iw usb|tail -$num
}

num=${1:-5} ใช้อาร์กิวเมนต์แรกโดยมีค่าเริ่มต้นเป็น 5 หากไม่ได้ระบุไว้

จากนั้นคุณสามารถทำได้:

$ d
# prints 5 lines
$ d 10
# prints 10 lines

หรือหากคุณเปลี่ยนตัวเลือกที่คุณใช้เล็กน้อย:

alias d="dmesg|grep -iw usb|tail -n 5"

จากนั้นคุณสามารถผ่าน-nตัวเลือกเพิ่มเติม:

$ d
# prints 5 lines
$ d -n 10
# prints 10 lines

หาก-nระบุหลายตัวเลือกจะใช้ตัวเลือกtailสุดท้ายเท่านั้น


สำหรับความท้าทายในการใช้งานเช่นตัวฉันเอง :) มันอาจจะเป็นประโยชน์ในการระบุสั้น ๆ ว่าจะวางฟังก์ชั่นอะไร ... ~/.bashrcหรือrc.localหรือที่ไหนก็ได้?
WinEunuuchs2Unix

@ WinEunuuchs2Unix ไม่ว่าจะวางนามแฝงที่ใดก็ตาม
muru

5

คุณจำเป็นต้องมีฟังก์ชั่นสำหรับการนี้ตามที่อธิบายไว้ในSOและที่นี่ ลองทำสิ่งต่อไปนี้:

foo() { /path/to/command "$@" ;}

และโทรfooด้วย:

foo arg1 arg2 arg3

4

แก้ไขข้อ จำกัด นามแฝงด้วยคำสั่งกลุ่มและ here-string

นามแฝงไม่สามารถโต้แย้งได้ แต่เราสามารถ "จำลอง" สิ่งนั้นได้ ยกตัวอย่างเช่นคำตอบของฉันในคำถามนี้

alias mkcd='{ IFS= read -r d && mkdir "$d" && cd "$d"; } <<<'

ประเด็นสำคัญที่เกิดขึ้นที่นี่:

  • เราใช้สร้างขึ้นในการอ่านสตริงลงในตัวแปรread dเพราะเราต้องการที่จะอ่านสตริงเต็มรูปแบบรวมถึงตัวละครที่ว่างเปล่า (ของขึ้นบรรทัดใหม่แท็บช่องว่าง) ที่เราใช้และทับขวาหลังปิดหนีกับIFS=-r
  • <<<ซึ่งตัวดำเนินการที่นี่คือสตริงช่วยให้เราสามารถเปลี่ยนเส้นทางสิ่งที่เราให้เป็นอาร์กิวเมนต์ไปยังmkcdนามแฝง; การใช้งานจะเป็นเช่นmkcd "some directory"
  • คำสั่งหลาย ๆ คำสั่งภายในนามแฝงจะถูกรวมและดำเนินการในเชลล์ปัจจุบันโดยใช้{ list; }โครงสร้าง (ซึ่งรู้จักกันgroup commandในbashคู่มือ) โปรดทราบว่าต้องมีการเว้นวรรคนำหน้า{และ;รายการคำสั่งแต่ละรายการ

ในตัวอย่างเฉพาะของคุณเราสามารถทำได้:

alias d='{ IFS= read -r n; dmesg | grep -iw "usb" | tail -n ${n:-5};} <<<'

เราสามารถใช้การแบ่งคำเพื่อเก็บอาร์กิวเมนต์ที่คั่นด้วยช่องว่าง:

bash-4.3$ { read -r a1 a2; echo "$a1"; echo "$a2";}  <<< "arg1 arg2"
arg1
arg2

หรือเราสามารถใช้อาร์เรย์เพื่อระบุอาร์กิวเมนต์หลายตัว:

bash-4.3$ { read -a arr; echo "${arr[1]}"; echo "${arr[0]}";}  <<< "arg1 arg2"
arg2
arg1

แต่วิธีนี้เป็นวิธีที่ดีหรือไม่?

ไม่จำเป็น. ปัญหาของวิธีการดังกล่าวคือมันมีความเฉพาะเจาะจงมาก - ไม่สามารถอ้างถึงข้อโต้แย้งได้ง่ายซึ่งหมายความว่าเราสามารถมีข้อโต้แย้งที่ไม่มีช่องว่างเท่านั้น

bash-4.3$ { read -r a1 a2; echo "$a1"; echo "$a2";}  <<< "'arg1 with space' arg2"
'arg1
with space' arg2

แน่นอนว่านี่ไม่ใช่สิ่งที่จะนำมาใช้กันอย่างแพร่หลายเพียงเพราะในโลกแห่งความเป็นจริงเราต้องจัดการกับข้อโต้แย้งที่ซับซ้อนดังนั้นวิธีการนี้จึงใช้ไม่ได้จริง ฟังก์ชั่นมีความยืดหยุ่นมากกว่า และความต้องการที่จะพูดสตริง args จะกลายเป็นที่น่ารำคาญอย่างรวดเร็ว

แม้จะมีข้อ จำกัด การทำงานกับสตริงอย่างง่าย ๆ เป็นข้อโต้แย้งที่เราสามารถแบ่งคำได้ดังนั้นบางส่วนทำให้เราสามารถโต้แย้งกับนามแฝงได้

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