วิธีการขยายนามแฝง bash


11

วิธีสร้างนามแฝงที่ขยายชื่อแทนอีกชื่อหนึ่งใน Bash จริง ๆ

ทำไม:

ผมเคยได้GREP_OPTIONSตั้งอยู่บน.bashrcบางสิ่งบางอย่างเช่นนี้

GREP_OPTIONS="-I --exclude=\*~"

ฉันยังมีสคริปต์ (ให้เราพูดsetup-java.sh) ซึ่งฉันจะโทรก่อนทำงานกับโปรเจ็กต์ Java บางตัว มันจะมีบรรทัด:

GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=classes"

ถ้าฉันใช้ Sass ด้วยฉันจะโทรหาsetup-sass.shซึ่งมีบรรทัด:

GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=\*/.sass-cache"

แต่GREP_OPTIONSเลิกใช้แล้วและเห็นได้ชัดว่าโซลูชันมาตรฐานคือสร้างนามแฝงหรือสคริปต์บางอย่าง ...


ฟังก์ชั่นทุบตีคืออะไร?
Jakuje

2
ฉันค่อนข้างเห็นด้วย - การใช้ฟังก์ชั่นเป็นตัวเลือกที่ดีกว่านามแฝง
ชาร์ลส์ดัฟฟี่

คำตอบ:


13

Bash เก็บค่าของ alias ในอาร์เรย์ที่เรียกว่า BASH_ALIASES :

$ alias foo=bar
$ echo ${BASH_ALIASES[foo]}
bar

ด้วยการขยายพารามิเตอร์ เราสามารถรับนามแฝงชุดสุดท้าย (ถ้ามี) หรือค่าเริ่มต้น:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~"

ตอนนี้ทำมันในsetup-java.sh:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~  --exclude-dir=classes"

... และในที่สุดเมื่อsetup-sass.sh:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=\*/.sass-cache"

หากมีการเรียกสามบรรทัดเราจะได้รับสิ่งที่เราต้องการ:

$ echo ${BASH_ALIASES[grep]:-grep}
grep -I --exclude=\*~ -I --exclude=\*~ --exclude-dir=classes -I --exclude=\*~ --exclude-dir=\*/.sass-cache

13

aliases โซ่ถ้าคุณจบพวกเขาด้วยช่องว่าง

alias print='printf %s\\n ' hey='"hello, fine fellow" '
print hey

hello, fine fellow

คุณสามารถเขียนสคริปต์ทั้งหมดด้วยวิธีนี้ถ้าคุณบ้าพอ อย่างไรก็ตามหากคุณต้องการขยายชื่อแทนให้ตรวจสอบให้แน่ใจว่านามแฝงที่คุณต้องการขยายจบลงในช่องว่าง

alias grep='printf "%s " -I --exclude=\*~ '    \
      exdir=' --exclude-dir=classes '          \
      exsass='--exclude-dir=\*/.sass-cache '
grep exdir exsass exdir exsass

-I --exclude=*~ --exclude-dir=classes --exclude-dir=*/.sass-cache --exclude-dir=classes --exclude-dir=*/.sass-cache

7
นี่คือสิ่งที่สวยงามน่ากลัว
user1717828

ว้าวนี่มันยอดเยี่ยมมาก ไม่ทราบเรื่องนี้ (และอาจจะไม่ใช้ประโยชน์มากนักเพราะฉันคิดว่ามันขัดกับกฎของความชัดเจน ) แต่มันก็ดีที่รู้! คำถามแม้ว่า: ทำไมพื้นที่เริ่มต้นexdir? (นั่นเป็นเพียงเพื่อการจัดตำแหน่งด้วยเหตุผลด้านความงาม?)
Wildcard

2
fnmatch(){ alias fnmatch='case $1 in '; while "${1:+:}" 2>&-; do eval 'fnmatch pattern list ;; esac'; shift; done; unalias fnmatch; }; alias pattern='${1:+*}) ' list=': do stuff '; fnmatch "$@"@Wildcard: การทำเช่นนี้aliasesช่วยให้คุณใช้การขยายรูปแบบได้โดยตรงและปลอดภัยยิ่งขึ้น คุณต้องการบริบทที่สองที่มีการevalเรียกจากภายในฟังก์ชั่น แต่มันก็ไม่ปลอดภัยตราบใดที่คุณpatternและlistควบคุมชื่อ caseพวกเขาสามารถทำลายในกรณีส่วนใหญ่แม้ในขณะที่พวกเขาไม่ได้เว้นแต่โจมตีบางอย่างรู้เท่าทันอย่างถูกต้องปิดให้บริการของคุณ
mikeserv

1
ฉันจะใช้นี้รูปแบบในของฉัน.bashrc: alias sudo='sudo 'นี้ช่วยให้ผมเรียกคำสั่ง aliased sudoของฉันทั้งหมดหลังจากที่ หากไม่มีที่ว่างมันจะไม่ทำงาน
2559

1
@ Wildcard - ฉันไม่ได้สนับสนุนการใช้งานดังกล่าวอย่างแน่นอน แต่มันเป็นความจริงที่คุณสามารถทำได้และมันก็เป็นความจริงที่คุณต้องลองอย่างน้อยก็บ้า
mikeserv

2

ฟังก์ชั่นเป็นตัวเลือกที่ดีกว่านามแฝงที่ขยายได้ที่นี่

grep_options=( )
grep() {
  exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
}

ด้วยวิธีนี้คุณมีสองตัวเลือกในการเพิ่มตัวเลือกให้กับสภาพแวดล้อม:

  • แก้ไขgrep_optionsอาร์เรย์; ตัวเลือกนี้สนับสนุนตัวเลือกที่มีช่องว่างอักขระตัวอักษรกลมและตัวพิมพ์มุมอื่น ๆ อย่างถูกต้อง:

    grep_options+=( --exclude-dir=classes --exclude-dir='*/.sass-cache' )
  • ใช้GREP_OPTIONSตัวแปรสเกลาร์แบบดั้งเดิมแม้จะมีข้อผิดพลาด (ดูBashFAQ # 50เพื่อทำความเข้าใจกับสิ่งเหล่านี้):

    GREP_OPTIONS+=' --exclude-dir=classes '

ที่กล่าวว่าหากคุณต้องการให้ตัวเลือกของคุณถูกสะท้อนโดยgrepอินสแตนซ์ที่เรียกใช้นอกเชลล์จะไม่มีทั้งนามแฝงและฟังก์ชันที่จะทำ คุณจะต้องวางสคริปต์ตัวห่อไว้ใน PATH ของคุณแทนgrepคำสั่งจริงแทน ตัวอย่างเช่น

# in ~/.bash_profile
[[ -e ~/bin ]] && PATH=$HOME/bin:$PATH

... และใน~/bin/grep:

#!/bin/bash

# load overrides to grep_options on GREP_OPTIONS from local dotfiles
source ~/.bash_profile
source ~/.bashrc

# ...and use them:
exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.