วิธีการพอร์ตไปยังสไตล์ทุบตีเพื่อเถ้า?


13

ashบางเวลาที่ผ่านมาฉันได้เขียนสคริปต์ทุบตีซึ่งขณะนี้ควรจะสามารถที่จะทำงานในสภาพแวดล้อมที่มี

ในbashมันเป็นเหมือน:

services=( "service1.service"
           "service2.service"                                       
           "service3.service" )  

for service in "${services[@]}"
do
   START $service                   
done

START()
{
   echo "Starting "$1
   systemctl start $1
}

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

สำหรับเหตุผลในการพกพาอาจเป็นเรื่องดีที่จะมีashโซลูชันที่บริสุทธิ์ แต่เนื่องจากฉันมีความแข็งแกร่งbusyboxในการจัดการของฉันฉันอาจเสียสละบางพกพา เฉพาะในกรณีที่ความสามารถในการอ่านดีขึ้นมากเนื่องจากสคริปต์ "clean" เป็นเมตริกเช่นกัน

ในกรณีนี้โซลูชันแบบพกพาและสะอาดจะเป็นอย่างไร

คำตอบ:


8

ก่อนที่อาร์เรย์จะอยู่ในbash, kshและเชลล์อื่น ๆ วิธีการปกติคือการเลือกตัวคั่นที่ไม่ได้อยู่ในองค์ประกอบใด ๆ (หรืออย่างใดอย่างหนึ่งที่ไม่ธรรมดาเพื่อลดการหลบหนีที่จำเป็น) และวนซ้ำสตริงที่มีองค์ประกอบทั้งหมด คั่นด้วยตัวคั่นนั้น ช่องว่างมักจะเป็นตัวเลือกตัวคั่นที่สะดวกที่สุดเนื่องจากเชลล์แยก "คำ" โดยช่องว่างตามค่าเริ่มต้นแล้ว (คุณสามารถตั้งค่า IFS หากคุณต้องการแยกในบางสิ่งที่แตกต่างกัน)

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

# backslash-escape any non-delimiter whitespace and all other characters that
# have special meaning to the shell, e.g. globs, parenthesis, ampersands, etc.
services='service1.service service2.service service3.service'

for s in $services ; do  # NOTE: do not double-quote $services here.
  START "$s"
done

$servicesไม่ควรอ้างอิงสองครั้งที่นี่เพราะเราต้องการให้เชลล์แยกออกเป็น "คำ"


3

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

set -- "service1.service" \
       "service2.service" \
       "service3.service"

for service in "$@"
do
   START $service
done

3

หากคุณต้องการอ้างถึงรายการบริการเพียงครั้งเดียวคุณสามารถใช้ here-doc:

while IFS= read -r service
do
   START "$service"
done << END
service1.service
service2.service
service3.service
END

โปรดทราบว่าชื่อบริการไม่ควรยกมาในรายการ (แม้ว่า"$service"อาจจะควรจะยกมาเว้นแต่คุณจะมีเหตุผลที่ดีที่จะไม่) หากคุณต้องการให้ชื่อบริการเยื้องใช้<<-แทน<<และเยื้องชื่อด้วยแท็บ:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.