ฉันคิดว่าคุณกำลังถามสองสิ่งที่แตกต่างกันที่นั่น
มีวิธีในการทุบตีพิมพ์ข้อมูลนี้โดยไม่วนซ้ำหรือไม่?
ใช่ แต่มันไม่ดีเท่าการใช้ลูป
มีวิธีที่สะอาดกว่าในการรับ / พิมพ์เฉพาะส่วน key = value ของเอาต์พุตหรือไม่?
ใช่for
วง มันมีข้อดีที่ไม่ต้องใช้โปรแกรมภายนอกตรงไปตรงมาและทำให้มันค่อนข้างง่ายในการควบคุมรูปแบบผลลัพธ์ที่แน่นอนโดยไม่ต้องประหลาดใจ
โซลูชันใด ๆ ที่พยายามจัดการกับผลลัพธ์ของdeclare -p
( typeset -p
) ต้องจัดการกับ a) ความเป็นไปได้ของตัวแปรที่มีวงเล็บหรือวงเล็บข) การอ้างอิงที่declare -p
ต้องเพิ่มเพื่อทำให้มันเป็นอินพุตที่ถูกต้องของเอาต์พุตสำหรับเชลล์
ตัวอย่างเช่นการขยายตัวของคุณb="${a##*(}"
กินค่าบางอย่างถ้าคีย์ / ค่าใด ๆ ที่มีวงเล็บเปิด นี่เป็นเพราะคุณใช้##
ซึ่งจะลบคำนำหน้าที่ยาวที่สุด เหมือนกันสำหรับc="${b%% )*}"
สำหรับเดียวกันแม้ว่าคุณจะสามารถจับคู่สำเร็จรูปสำเร็จรูปที่พิมพ์ได้declare
มากกว่าแน่นอนคุณยังคงมีเวลาลำบากหากคุณไม่ต้องการให้มีการอ้างอิงทั้งหมด
มันไม่ได้ดูดีมากถ้าคุณต้องการมัน
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
ด้วยการfor
วนซ้ำมันง่ายกว่าที่จะเลือกรูปแบบผลลัพธ์ตามที่คุณต้องการ:
# without quoting
$ for x in "${!array[@]}"; do printf "[%s]=%s\n" "$x" "${array[$x]}" ; done
[def]="foo bar"
[abc]='foobar'
# with quoting
$ for x in "${!array[@]}"; do printf "[%q]=%q\n" "$x" "${array[$x]}" ; done
[def]=\"foo\ bar\"
[abc]=\'foobar\'
จากตรงนั้นมันก็ง่ายต่อการเปลี่ยนรูปแบบเอาต์พุตอื่น (ลบวงเล็บเหลี่ยมรอบคีย์วางคู่คีย์ / ค่าทั้งหมดในบรรทัดเดียว ... ) หากคุณต้องการอ้างถึงสิ่งอื่นนอกเหนือจากตัวเชลล์คุณจะต้องดำเนินการเอง แต่อย่างน้อยคุณก็มีข้อมูลดิบที่จะใช้งานได้ (ถ้าคุณมีบรรทัดใหม่ในคีย์หรือค่าคุณอาจจะต้องมีการพูด)
ด้วย Bash ปัจจุบัน (4.4 ฉันคิดว่า) คุณสามารถใช้printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
แทนprintf "%q=%q"
ได้ มันสร้างรูปแบบที่ยกมาค่อนข้างดีกว่า แต่เป็นงานอีกเล็กน้อยที่ต้องจำไว้ในการเขียน (และมันพูดราคาตัวพิมพ์ที่มุมของ@
เป็นคีย์อาร์เรย์ซึ่ง%q
ไม่ได้อ้างอิง)
หากลูป for ดูเหมือนว่าเหนื่อยเกินกว่าจะเขียนให้บันทึกฟังก์ชันไว้ที่ใดที่หนึ่ง (โดยไม่ต้องใส่เครื่องหมายที่นี่):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
จากนั้นใช้เพียง:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
ทำงานร่วมกับอาร์เรย์ที่มีการจัดทำดัชนีเช่นกัน:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
แตกต่างไม่เหมาะสำหรับ reinput กับเปลือกถ้าอาร์เรย์มี@
คีย์% จากไตรมาสไม่ได้พูดมันและเป็นไวยากรณ์ผิดพลาดในa=([@]=value)
bash