หากคุณมี Git และตกลงกับข้อ จำกัด ที่ไม่สามารถใช้เครื่องหมายขีดล่างในชื่อคีย์คุณสามารถใช้git configเป็นตัวแยกวิเคราะห์ / ตัวแก้ไข INI เอนกประสงค์
มันจะจัดการแยกคีย์คู่ / ค่าจากรอบ ๆ=และยกเลิกช่องว่างที่ไม่มีนัยสำคัญรวมทั้งคุณได้รับความคิดเห็น (ทั้ง;และ#) และประเภทการข่มขู่โดยทั่วไปฟรี ฉันได้รวมตัวอย่างการทำงานที่สมบูรณ์สำหรับอินพุตของ OP .iniและเอาท์พุทที่ต้องการ (อาเรย์เชื่อมโยง Bash) ไว้ด้านล่าง
อย่างไรก็ตามให้ไฟล์ config แบบนี้
; mytool.ini
[section1]
inputdir = ~/some/dir
enablesomefeature = true
enablesomeotherfeature = yes
greeting = Bonjour, Monde!
[section2]
anothersetting = 42
... หากคุณต้องการวิธีแก้ปัญหาที่รวดเร็วและสกปรกและไม่ได้แต่งงานกับความคิดของการตั้งค่าในอาเรย์ของ Bash associative คุณสามารถทำได้โดยใช้:
eval $(git config -f mytool.ini --list | tr . _)
# or if 'eval' skeeves you out excessively
source <(git config -f mytool.ini --list | tr . _)
ซึ่งสร้างตัวแปรสภาพแวดล้อมที่มีชื่อsectionname_variablenameในสภาพแวดล้อมปัจจุบัน แน่นอนว่าสิ่งนี้ใช้ได้ผลก็ต่อเมื่อคุณสามารถเชื่อมั่นได้ว่าไม่มีค่าใดที่จะมีจุดหรือช่องว่าง (ดูด้านล่างสำหรับวิธีแก้ปัญหาที่มีประสิทธิภาพมากกว่า)
ตัวอย่างง่ายๆอื่น ๆ
ดึงค่าตามอำเภอใจโดยใช้ฟังก์ชั่นเปลือกเพื่อบันทึกการพิมพ์:
function myini() { git config -f mytool.ini; }
นามแฝงจะตกลงที่นี่ด้วย แต่ผู้ที่ยังไม่ได้ขยายตัวได้ตามปกติในสคริปต์เชลล์ [ 1 ] และชื่อแทนอยู่แล้วจะถูกแทนที่โดยฟังก์ชั่นเปลือก "เกือบทุกจุดประสงค์" [ 2 ] ตามที่ทุบตีหน้าคน
myini --list
# result:
# section1.inputdir=~/some/dir
# section1.enablesomefeature=true
# section1.enablesomeotherfeature=yes
# section2.anothersetting=42
myini --get section1.inputdir
# result:
# ~/some/dir
ด้วย--typeตัวเลือกนี้คุณสามารถตั้งค่า "canonicalize" เป็นจำนวนเต็มบูลีนหรือพา ธ (ขยายโดยอัตโนมัติ~):
myini --get --type=path section1.inputdir # value '~/some/dir'
# result:
# /home/myuser/some/dir
myini --get --type=bool section1.enablesomeotherfeature # value 'yes'
# result:
# true
ตัวอย่างรวดเร็วและสกปรกที่แข็งแกร่งขึ้นเล็กน้อย
ทำให้ตัวแปรทั้งหมดmytool.iniพร้อมใช้งานเช่นเดียวกับSECTIONNAME_VARIABLENAMEในสภาพแวดล้อมปัจจุบันรักษาช่องว่างภายในในค่าคีย์:
source <(
git config -f mytool.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/\U\1_\2\E="\3"/'
)
สิ่งที่แสดงออกอย่างใจเย็นกำลังทำในภาษาอังกฤษคือ
- การค้นหากลุ่มของอักขระที่ไม่ใช่ช่วงเวลาจนถึงจุดหนึ่งโดยจดจำว่าเป็น
\1แล้ว
- การค้นหากลุ่มของอักขระจนถึงเครื่องหมายเท่ากับให้จำว่าเป็น
\2และ
- การค้นหาตัวอักษรทั้งหมดหลังจากเครื่องหมายเท่ากับ
\3
- ในที่สุดในสตริงแทนที่
- ชื่อส่วน + ชื่อตัวแปรเป็นตัวพิมพ์ใหญ่และ
- ส่วนของค่าคือการเสนอราคาสองครั้งในกรณีที่มันมีตัวละครที่มีความหมายพิเศษกับเปลือกถ้าไม่ได้ยกมา (เช่นช่องว่าง)
\Uและ\Eวนเวียนอยู่ในสตริงทดแทน (ซึ่งบนกรณีที่เป็นส่วนหนึ่งของสตริงทดแทน) เป็น GNU sedนามสกุล สำหรับ macOS และ BSD คุณเพียงแค่ใช้หลาย-eนิพจน์เพื่อให้ได้ผลลัพธ์ที่เหมือนกัน
การจัดการกับอัญประกาศและช่องว่างที่ฝังอยู่ในชื่อส่วน (ซึ่งgit configอนุญาตให้) ถูกทิ้งไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน:)
การใช้ชื่อส่วนเป็นคีย์ในอาเรย์ของ Bash
ได้รับ:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
สิ่งนี้จะสร้างผลลัพธ์ที่ OP ต้องการโดยเพียงแค่จัดเรียงบางส่วนใหม่ในนิพจน์แทนที่ sed และจะทำงานได้ดีโดยไม่ต้อง GNU sed:
source <(
git config -f foo.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/declare -A \2["\1"]="\3"/'
)
ฉันคาดการณ์ว่าอาจมีความท้าทายบางอย่างจากการอ้างถึง.iniไฟล์ในโลกแห่งความจริงแต่มันก็ใช้ได้กับตัวอย่างที่มีให้ ผลลัพธ์:
declare -p {session,path}
# result:
# declare -A session=([barfoo]="bar" [foobar]="foo" )
# declare -A path=([barfoo]="/some/path" [foobar]="/some/path" )