Nếu bạn có sẵn Git và ổn với điều kiện không thể sử dụng dấu gạch dưới trong tên khóa, bạn có thể sử dụng git config
làm trình phân tích / trình soạn thảo INI cho mục đích chung.
Nó sẽ xử lý phân tích cặp khóa / giá trị từ xung quanh =
và loại bỏ khoảng trắng không đáng kể, cộng với việc bạn nhận được bình luận (cả ;
và #
) và loại cưỡng chế về cơ bản miễn phí. Tôi đã bao gồm một ví dụ hoạt động hoàn chỉnh cho đầu vào của OP .ini
và đầu ra mong muốn (mảng kết hợp Bash), bên dưới.
Tuy nhiên, được cung cấp một tệp cấu hình như thế này
; mytool.ini
[section1]
inputdir = ~/some/dir
enablesomefeature = true
enablesomeotherfeature = yes
greeting = Bonjour, Monde!
[section2]
anothersetting = 42
Càng cung cấp cho bạn chỉ cần một giải pháp nhanh chóng và bẩn thỉu, và không kết hôn với ý tưởng có các thiết lập trong một mảng kết hợp Bash, bạn có thể thoát khỏi chỉ với:
eval $(git config -f mytool.ini --list | tr . _)
# or if 'eval' skeeves you out excessively
source <(git config -f mytool.ini --list | tr . _)
mà tạo ra các biến môi trường được đặt tên sectionname_variablename
trong môi trường hiện tại. Tất nhiên, điều này chỉ hoạt động nếu bạn có thể tin tưởng rằng không có giá trị nào của bạn sẽ chứa một khoảng thời gian hoặc khoảng trắng (xem bên dưới để biết giải pháp mạnh mẽ hơn).
Ví dụ đơn giản khác
Tìm nạp các giá trị tùy ý, sử dụng hàm shell để lưu kiểu gõ:
function myini() { git config -f mytool.ini; }
Một bí danh cũng sẽ ổn, ở đây, nhưng những cái đó thường không được mở rộng trong tập lệnh shell [ 1 ], và dù sao thì các bí danh được thay thế bởi các hàm shell "cho hầu hết mọi mục đích", [ 2 ], theo trang Bash man .
myini --list
# result:
# section1.inputdir=~/some/dir
# section1.enablesomefeature=true
# section1.enablesomeotherfeature=yes
# section2.anothersetting=42
myini --get section1.inputdir
# result:
# ~/some/dir
Với --type
tùy chọn, bạn có thể "chuẩn hóa" các cài đặt cụ thể dưới dạng số nguyên, booleans hoặc đường dẫn (tự động mở rộng ~
):
myini --get --type=path section1.inputdir # value '~/some/dir'
# result:
# /home/myuser/some/dir
myini --get --type=bool section1.enablesomeotherfeature # value 'yes'
# result:
# true
Ví dụ nhanh và bẩn mạnh mẽ hơn một chút
Làm cho tất cả các biến mytool.ini
có sẵn như SECTIONNAME_VARIABLENAME
trong môi trường hiện tại, duy trì khoảng trắng bên trong trong các giá trị chính:
source <(
git config -f mytool.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/\U\1_\2\E="\3"/'
)
Những gì biểu hiện sed đang làm, trong tiếng Anh, là
- tìm thấy một loạt các nhân vật không có thời hạn cho đến một khoảng thời gian
\1
, sau đó nhớ rằng
- tìm thấy một loạt các ký tự cho đến một dấu bằng, nhớ rằng như
\2
, và
- tìm tất cả các ký tự sau dấu bằng
\3
- cuối cùng, trong chuỗi thay thế
- tên phần + tên biến được viết hoa và
- phần giá trị được trích dẫn kép, trong trường hợp nó chứa các ký tự có ý nghĩa đặc biệt với shell nếu không được trích dẫn (như khoảng trắng)
Các chuỗi \U
và \E
chuỗi trong chuỗi thay thế (chữ hoa là một phần của chuỗi thay thế) là sed
phần mở rộng GNU . Trên macOS và BSD, bạn chỉ cần sử dụng nhiều-e
biểu thức để đạt được hiệu ứng tương tự.
Xử lý các trích dẫn và khoảng trắng được nhúng trong tên phần ( git config
cho phép) được để lại như một bài tập cho người đọc.:)
Sử dụng tên phần làm khóa vào một mảng kết hợp Bash
Được:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
Điều này sẽ tạo ra kết quả mà OP đang yêu cầu, chỉ đơn giản bằng cách sắp xếp lại một số ảnh chụp trong biểu thức thay thế sed và sẽ hoạt động tốt mà không cần GNU sed:
source <(
git config -f foo.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/declare -A \2["\1"]="\3"/'
)
Tôi dự đoán có thể có một số thách thức với việc trích dẫn cho một .ini
tệp trong thế giới thực , nhưng nó hoạt động với ví dụ được cung cấp. Kết quả:
declare -p {session,path}
# result:
# declare -A session=([barfoo]="bar" [foobar]="foo" )
# declare -A path=([barfoo]="/some/path" [foobar]="/some/path" )