กำลังเตรียมใช้งานตัวแปร Bash - จำเป็นต้องมีการแนะนำหรือกำหนดตามที่คุณไป


9

มีข้อได้เปรียบ / เสียเปรียบในการเตรียมใช้งานค่าของตัวแปร bash ในสคริปต์ไม่ว่าจะก่อนโค้ดหลักหรือตัวแปรโลคัลในฟังก์ชันก่อนกำหนดค่าจริงให้กับมัน?

ฉันต้องทำอะไรแบบนี้หรือเปล่า:

init()
{
    name=""
    name=$1
}

init "Mark"

มีความเสี่ยงของตัวแปรที่เริ่มต้นด้วยค่าขยะ (หากไม่ได้กำหนดค่าเริ่มต้น) และมีผลกระทบเชิงลบของค่าของตัวแปรหรือไม่?


2
คุณได้รับแนวคิดนี้ที่ไหน

6
@DoritoStyle ถ้ามีคนใช้ภาษาระดับต่ำกว่าเช่น C นี่จะเป็นสิ่งที่ถูกต้องสมบูรณ์แบบที่ควรคำนึงถึง
Kusalananda

@Kusalananda รหัส C นั้นเทียบเท่าname = ""; name = argv[1];หรือไม่ และนั่นก็ไม่ไร้สาระเหมือนกันหรือ
Joseph Sible-Reinstate Monica

1
@ JosephSible-ReinstateMonica ใช่ รหัส C ที่คุณโพสต์นั้นไม่มีจุดหมาย ใน C แม้ว่าเมื่อเทียบกับเชลล์ตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้นจะไม่มีค่าที่กำหนดชัดเจน ซึ่งหมายความว่าการเริ่มต้นตัวแปรในภาษาเช่น C เหมาะสมในหลาย ๆ สถานการณ์ การทำเช่นนั้นในเชลล์ไม่จำเป็น การเริ่มต้นตัวแปรใน C เท่านั้นเพื่อตั้งค่าให้เป็นค่าอื่นทันทีนั้นไม่มีจุดหมายในขณะที่คุณชี้ให้เห็น
Kusalananda

คำตอบ:


22

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

มีความรู้ของฉันไม่มีคำแนะนำที่บอกว่าคุณควรเริ่มต้นตัวแปรอย่างชัดเจนเพื่อสตริงว่าง ในความเป็นจริงการทำเช่นนั้นอาจปกปิดข้อผิดพลาดในบางสถานการณ์ (ข้อผิดพลาดที่อาจเห็นได้ชัดหากทำงานภายใต้set -uดูด้านล่าง)

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

หากnounsetตั้งค่าตัวเลือก shell ด้วยset -o nounsetหรือset -uการอ้างอิงตัวแปร unset จะทำให้เชลล์สร้างข้อผิดพลาด (และเชลล์ที่ไม่มีการโต้ตอบจะสิ้นสุดลง):

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

หรือในbash:

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

ตัวแปรเชลล์จะถูกเตรียมใช้งานโดยสภาพแวดล้อมหากชื่อของตัวแปรสอดคล้องกับตัวแปรสภาพแวดล้อมที่มีอยู่

หากคุณคาดหวังว่าคุณกำลังใช้ตัวแปรที่อาจเริ่มต้นสภาพแวดล้อมด้วยวิธีนี้ (และหากไม่ต้องการ) คุณอาจยกเลิกการตั้งค่าอย่างชัดเจนก่อนส่วนหลักของสคริปต์ของคุณ:

unset myvariable    # unset so that it doesn't inherit a value from the environment

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

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


3
ในขณะที่ไม่มีค่าในการตั้งค่าตัวแปรให้เป็นค่าว่างแล้วตั้งค่าทันทีตาม OP อย่างแท้จริง แต่มีค่าในการตั้งค่าค่าว่าง (หรือการunsetทิ้ง) ก่อนที่จะเรียกใช้forหรือwhileวนรอบบางอย่างเพื่อตั้งค่าการคำนวณ มูลค่าหากมีโอกาสใด ๆ ที่ลูปจะไม่ทำงานเนื่องจากเงื่อนไขไม่ได้ถูกพบ และตัวแปรอาจถูกตั้งค่าเป็นค่าอื่น ๆ ในสภาพแวดล้อมที่สคริปต์สืบทอด แต่มันเป็นเนื้อหาที่ดีกว่าที่จะใส่ทุกอย่างในและกำหนดตัวแปรเป็นmain() local
Monty Harder

นอกจากนี้คุณยังสามารถตรวจจับตัวแปรที่ไม่ได้ตั้งค่าโดยใช้ตัวดำเนินการขยายพารามิเตอร์โดยไม่ต้องเว้น:${myvariable-defaultvalue}
วรรค

3

แก้ไข : อ๊ะดูเหมือนประกาศจะแตกต่างจากการเริ่มต้น ฉันจะออกจากที่นี่ต่อไปดังนั้นนักเขียนมือใหม่อย่างฉันสามารถเรียนรู้จากความผิดพลาด


ข้อดีของการประกาศตัวแปรท้องถิ่นในฟังก์ชั่นคือคุณสามารถคัดลอกรหัสได้อย่างง่ายดาย

ตัวอย่างเช่นฉันมีฟังก์ชั่น:

foo(){
    local name
    name="$1"
    echo "$name"
}

หากฉันต้องการทำให้เป็นสคริปต์ฉันแค่เพิกเฉยlocalคำสั่งและคัดลอกทุกอย่างอื่น:

#!/bin/bash
name="$1"
echo "$name"

หากการประกาศและการมอบหมายอยู่ในบรรทัดเดียวกันฉันจะต้องแก้ไขlocalส่วนด้วยตนเองก่อนที่จะเปลี่ยนเป็นสคริปต์:

foo(){
    local name="$1"
    echo "$name"
}

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


1
คำถามไม่ได้เกี่ยวกับการรวมการประกาศและการเริ่มต้น มันเกี่ยวกับว่าจะเริ่มต้นด้วยค่าที่ว่างเปล่าก่อนที่จะกำหนดมูลค่าที่แท้จริง
Barmar

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