Alias ​​scoping ในฟังก์ชัน bash


9

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

นี่คือตัวอย่างเล็กน้อย:

# aliases.sh
alias fooAlias='echo "this will never work!"'  

.

# .bashrc
function setupLotsOfThings() {
    source aliases.sh
    fooAlias
}

.

ตอนนี้ถ้าฉันเพียงแค่aliases.shโต้ตอบแหล่งที่มาสิ่งที่ทำงานตามที่คาดไว้:

[mycomputer]~/ $ source aliases.sh
[mycomputer]~/ $ fooAlias
this will never work!

อย่างไรก็ตามถ้าฉันเรียกฟังก์ชันที่กำหนดใน. bashrc ของฉันแทนมันจะไม่รู้จักนามแฝงหลังจากหาคำจำกัดความของมัน:

[mycomputer]~/ $ setupLotsOfThings
-bash: fooAlias: command not found

เกิดขึ้นที่นี่คืออะไร? มีบางสิ่งที่ฉันขาดหายไปเกี่ยวกับขอบเขตของaliasคำสั่งเมื่อใช้ในฟังก์ชันหรือไม่?

แก้ไข:ฉันจะเพิ่มรายละเอียดนอกเหนือจากตัวอย่างเล็ก ๆ น้อย ๆ เพื่อส่องแสงสิ่งที่ฉันพยายามทำให้สำเร็จ

สำหรับงานของฉันฉันพัฒนาและใช้งานซอฟต์แวร์จำนวนมากในคลัสเตอร์และ / หรือตาราง ฉันมีหลายโครงการที่ต้องการสภาพแวดล้อมที่แตกต่างกันโดยสิ้นเชิงเช่นรุ่น gcc ที่แตกต่างกันการเปิดตัวซอฟต์แวร์เฉพาะการกำหนดค่าและเส้นทางข้อมูลและตัวแปรสภาพแวดล้อมต่างๆ ผู้ดูแลระบบจัดเตรียมสคริปต์เพื่อตั้งค่าสิ่งต่าง ๆ โดยปกติจะกำหนดฟังก์ชันเปลือกหรือนามแฝงซึ่งเรียกใช้ฟังก์ชันหรือนามแฝงอื่น ๆ หรือเรียกใช้สคริปต์ต่าง ๆ สำหรับฉันมันเป็นกล่องดำ

ฉันต้องการตั้งค่าสภาพแวดล้อมต่าง ๆ ของฉันเองด้วยคำสั่งเดียว ขณะนี้ฉันทำสิ่งที่ชอบ:

[mycomputer]~/ $ source /some/environment/setup/script.sh
[mycomputer]~/ $ aliasToSetupSomeSoftwareVersion    #this was defined in the above
[mycomputer]~/ $ anotherAliasForOtherSoftware
[mycomputer]~/ $ source /maybe/theres/another/script.sh
[mycomputer]~/ $ runSomeOtherSetup      # this was defined in the new script

โดยทั่วไปคำสั่งเหล่านี้จะต้องทำงานตามลำดับ โดยพื้นฐานแล้วความคิดของฉันคือการคัดลอกบรรทัดด้านบนลงในบล็อกฟังก์ชัน แต่ตามตัวอย่างดั้งเดิมแสดงให้เห็นว่ามันไม่ได้ผล การแก้ปัญหาทางเลือกเป็นมากกว่าการต้อนรับ!

คำตอบ:


10

ทางเลือกอื่นคือการวางคำสั่งเหล่านั้นลงในไฟล์ข้อความแทนฟังก์ชั่นบล็อก สิ่งที่ต้องการ:

## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases

source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup

บันทึกสิ่งsetup1.shที่คุณต้องการ เคล็ดลับคือจากนั้นแหล่งไฟล์นี้ไม่ได้ดำเนินการ:

$ source setup1.sh

ที่จะเรียกใช้ชื่อแทนที่อยู่ในสคริปต์และทำให้พร้อมใช้งานสำหรับเชลล์ปัจจุบันของคุณ

คุณสามารถทำให้กระบวนการง่ายขึ้นโดยการเพิ่มสิ่งนี้ลงใน.bashrc:

alias setupLotsOfThings="source setup1.sh"

ตอนนี้คุณสามารถเรียกใช้setupLotsOfThingsและรับพฤติกรรมที่คุณต้องการได้จากฟังก์ชั่น


คำอธิบาย

มีสองประเด็นที่นี่ ครั้งแรกนามแฝงจะไม่สามารถใช้ได้กับฟังก์ชั่นที่มีการประกาศ แต่เมื่อฟังก์ชันนั้นได้ออกและครั้งที่สองที่ชื่อแทนจะไม่สามารถใช้ได้ภายในสคริปต์ ทั้งสองอธิบายไว้ในส่วนเดียวกันของman bash:

นามแฝงจะไม่ถูกขยายเมื่อเชลล์ไม่ได้ทำงานยกเว้นว่าตัวเลือกเชลล์ expand_aliases ถูกตั้งค่าโดยใช้ shopt (ดูคำอธิบายของ shopt ภายใต้คำสั่ง SHELL BUILTIN ด้านล่าง)

กฎที่เกี่ยวข้องกับคำจำกัดความและการใช้นามแฝงค่อนข้างสับสน Bash จะอ่านบรรทัดที่สมบูรณ์อย่างน้อยหนึ่งรายการก่อนดำเนินการคำสั่งใด ๆ ในบรรทัดนั้น นามแฝงจะถูกขยายเมื่อคำสั่งถูกอ่านไม่ใช่เมื่อถูกเรียกใช้งาน ดังนั้นคำนิยามนามแฝงที่ปรากฏบนบรรทัดเดียวกันกับคำสั่งอื่นจะไม่มีผลจนกว่าจะอ่านบรรทัดอินพุตถัดไป คำสั่งที่ตามหลังนิยาม alias บนบรรทัดนั้นจะไม่ได้รับผลกระทบจาก alias ใหม่ ลักษณะการทำงานนี้ยังเป็นปัญหาเมื่อใช้งานฟังก์ชัน นามแฝงจะถูกขยายเมื่อมีการอ่านคำจำกัดความของฟังก์ชั่นไม่ใช่เมื่อเรียกใช้งานฟังก์ชั่นเนื่องจากคำจำกัดความของฟังก์ชั่นเป็นคำสั่งผสม ดังนั้นนามแฝงที่กำหนดในฟังก์ชั่นจึงไม่
สามารถใช้งานได้จนกว่าจะมีการใช้งานฟังก์ชันดังกล่าว
เพื่อความปลอดภัยให้ใส่คำจำกัดความของนามแฝงบนบรรทัดแยกต่างหากเสมอและห้ามใช้นามแฝงในคำสั่ง com‐ pound

จากนั้นจะมีความแตกต่างระหว่างการดำเนินการและการจัดหาไฟล์ โดยพื้นฐานแล้วการรันสคริปต์ทำให้มันทำงานในเชลล์แยกต่างหากในขณะที่การจัดหามันทำให้มันทำงานในเชลล์ปัจจุบัน ดังนั้นการจัดหาsetup.shทำให้นามแฝงพร้อมใช้งานกับพาเรนต์เชลล์ในขณะดำเนินการตามที่สคริปต์จะไม่ทำ


ฉันกำลังทำงานกับคลัสเตอร์และมีสคริปต์ "aliasing" หลายอย่างที่ช่วยในการตั้งค่าสภาพแวดล้อมซอฟต์แวร์ ฯลฯ สคริปต์ alias กำหนดนามแฝงที่แตกต่างกันมากมาย เป้าหมายของฉันคือการเรียกใช้สภาพแวดล้อมที่เฉพาะเจาะจงโดยการจัดหานามแฝงที่ถูกต้องแล้วเรียกใช้นามแฝงเหล่านั้น (บางส่วน) ฉันต้องการทำสิ่งนี้ในคำสั่งเดียวแทนที่จะต้องใช้คำสั่งหลาย ๆ ตัวตามลำดับ
ไล่ล่า

และ PS สคริปต์ที่ตั้งค่านามแฝงนั้นน่าเสียดายมากและช้านิดหน่อย (เพราะมันแตะไฟล์หลาย ๆ ไฟล์ใน NFS) ดังนั้นฉันจึงไม่ชอบที่จะแหล่งทุกสิ่งเหล่านี้เช่นเวลาเข้าสู่ระบบ
ไล่ล่า

@chase แต่พวกเขามีแหล่งที่มาเฉพาะเมื่อคุณเรียกใช้setupLotsOfThingsพวกเขาก็ไม่สามารถใช้ได้กับฟังก์ชั่นตัวเอง มันทำงานกับเชลล์ที่คุณเรียกใช้ฟังก์ชัน อย่างไรก็ตามหากฟังก์ชั่นของคุณเป็นแค่ชื่อแทนทำไมไม่ใช้นามแฝง? ตัวอย่างเช่นalias setupstuff="source aliases.sh".
terdon

ขวา แต่ผมไม่ได้กังวลเกี่ยวกับขอบเขตต่อ se เป็นการดีที่ฉันเพียงต้องการรวม "สิ่งที่มา" และ "เรียกใช้นามแฝง" ขั้นตอนในที่เดียว บางทีมันสามารถทำได้ด้วย 3 ฟังก์ชั่น? ฟังก์ชัน sourceStuff () {source ... }; ฟังก์ชั่น runStuff () {someAlias; ... }; ฟังก์ชัน setupLotsOfThings () {sourceStuff; runStuff; };
ไล่ล่า

@chase ใช่ฉันคิดอย่างนั้น แต่มันไม่ทำงาน :) คุณช่วยขยายคำถามของคุณด้วยสิ่งที่คุณต้องทำเพิ่มเติมได้ไหม? ฟังก์ชั่นสามารถจัดการกับความซับซ้อนมากเท่านั้นคุณอาจต้องเขียนสคริปต์เล็กน้อย
terdon

7

ที่จริงแล้วนามแฝงของคุณจะพร้อมใช้งานหลังจากโหลดฟังก์ชั่นแล้ว! คุณสามารถใช้มันในเชลล์เชิงโต้ตอบของคุณหรือในของคุณ.bashrcหลังจากดำเนินการฟังก์ชั่น

ข้อ จำกัด คือนามแฝงในนิยามฟังก์ชันจะถูกขยายเมื่ออ่านนิยามฟังก์ชันไม่ใช่เมื่อประเมินฟังก์ชัน นี่เป็นข้อ จำกัด ของการทุบตี ดังนั้นจะใช้งานได้:

function setupLotsOfThings() {
    source aliases.sh
}
setupLotsOfThings
fooAlias

แต่ไม่ใช่สิ่งนี้:

function setupLotsOfThings() {
    source aliases.sh
}
function useTheAliases() {
    fooAlias
}
setupLotsOfThings
useTheAliases

หากคุณต้องการนามแฝงที่สามารถใช้งานได้ภายในฟังก์ชั่นและสามารถกำหนดได้หลังจากแยกวิเคราะห์ฟังก์ชันแล้วให้ใช้ฟังก์ชันแทน จำไว้ว่าคุณสามารถใช้commandbuiltin เพื่อเรียกใช้คำสั่งภายนอกจากฟังก์ชั่นที่มีชื่อเดียวกัน

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