ฉันจะกำหนดผลลัพธ์ของฟังก์ชันให้กับตัวแปรโดยใช้ bash ได้อย่างไร


97

ฉันมีฟังก์ชันทุบตีที่ให้ผลลัพธ์บางอย่าง:

function scan {
  echo "output"
}

ฉันจะกำหนดผลลัพธ์นี้ให้กับตัวแปรได้อย่างไร

กล่าวคือ. VAR = scan (แน่นอนว่าไม่ได้ผล - ทำให้ VAR เท่ากับสตริง "scan")


1
ที่เกี่ยวข้อง: stackoverflow.com/q/3236871/435605
AlikElzin-kilaka

คำตอบ:


145
VAR=$(scan)

วิธีเดียวกับโปรแกรม


3
ฉันพบว่ามีการตัดบรรทัดใหม่เมื่อฉันทำ "echo $ VAR" หากฉันเสนอราคา $ VAR แทนมันจะยังคงขึ้นบรรทัดใหม่
Brent

2
นั่นไม่ถูกต้อง 100% การแทนที่คำสั่งจะลากเส้นบรรทัดใหม่เสมอ
TheBonsai

7
สิ่งนี้จะสร้าง subshell; มีวิธีใดบ้างที่จะทำในเปลือกเดียวกัน
การชดใช้อย่าง จำกัด

24

คุณสามารถใช้ฟังก์ชัน bash ในคำสั่ง / pipelines ได้เช่นเดียวกับที่คุณใช้โปรแกรมทั่วไป ฟังก์ชั่นนี้ยังพร้อมใช้งานสำหรับ subshells และสกรรมกริยาการแทนที่คำสั่ง:

VAR=$(scan)

เป็นวิธีที่ตรงไปตรงมาเพื่อให้บรรลุผลลัพธ์ที่คุณต้องการในกรณีส่วนใหญ่ ฉันจะร่างกรณีพิเศษด้านล่าง

การรักษา Newlines ต่อท้าย:

ผลข้างเคียงอย่างหนึ่ง (มักจะเป็นประโยชน์) ของการแทนที่คำสั่งคือมันจะตัดบรรทัดใหม่ที่ต่อท้ายออก หากต้องการรักษาบรรทัดใหม่ต่อท้ายเราสามารถต่อท้ายอักขระดัมมี่เข้ากับเอาต์พุตของ subshell และต่อจากนั้นจึงดึงออกด้วยการขยายพารามิเตอร์

function scan2 () {
    local nl=$'\x0a';  # that's just \n
    echo "output${nl}${nl}" # 2 in the string + 1 by echo
}

# append a character to the total output.
# and strip it with %% parameter expansion.
VAR=$(scan2; echo "x"); VAR="${VAR%%x}"

echo "${VAR}---"

พิมพ์ (3 บรรทัดใหม่เก็บไว้):

output


---

ใช้พารามิเตอร์เอาต์พุต: หลีกเลี่ยง subshell (และรักษาบรรทัดใหม่)

หากสิ่งที่ฟังก์ชันพยายามบรรลุคือการ "คืนค่า" สตริงให้เป็นตัวแปรโดยใช้ bash v4.3 ขึ้นไปเราสามารถใช้สิ่งที่เรียกว่า a nameref. Namerefs อนุญาตให้ฟังก์ชันใช้ชื่อของพารามิเตอร์เอาต์พุตของตัวแปรอย่างน้อยหนึ่งตัว คุณสามารถกำหนดสิ่งต่างๆให้กับตัวแปร nameref และเหมือนกับว่าคุณเปลี่ยนตัวแปรที่ 'ชี้ไปที่ / อ้างอิง'

function scan3() {
    local -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

VAR="some prior value which will get overwritten"

# you pass the name of the variable. VAR will be modified.
scan3 VAR

# newlines are also preserved.
echo "${VAR}==="

พิมพ์:

output

===

แบบฟอร์มนี้มีข้อดีเล็กน้อย กล่าวคืออนุญาตให้ฟังก์ชันของคุณแก้ไขสภาพแวดล้อมของผู้โทรโดยไม่ต้องใช้ตัวแปรส่วนกลางทุกที่

หมายเหตุ: การใช้ namerefs สามารถปรับปรุงประสิทธิภาพของโปรแกรมของคุณได้อย่างมากหากฟังก์ชันของคุณต้องพึ่งพา bash builtins เป็นอย่างมากเนื่องจากจะหลีกเลี่ยงการสร้าง subshell ที่ถูกทิ้งในภายหลัง โดยทั่วไปสิ่งนี้เหมาะสมกว่าสำหรับฟังก์ชันขนาดเล็กที่ใช้ซ้ำบ่อยครั้งเช่นฟังก์ชันที่ลงท้ายด้วยecho "$returnstring"

สิ่งนี้มีความเกี่ยวข้อง https://stackoverflow.com/a/38997681/5556676


0

ฉันคิดว่า init_js ควรใช้การประกาศแทน local!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

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