Chỉnh sửa tập tin cấu hình thông qua tập lệnh bash


9

Tôi đã cố gắng viết một tập lệnh bash đơn giản mà tôi sẽ sử dụng để cài đặt một ứng dụng và cập nhật tập tin cấu hình của nó. Tôi đang gặp khó khăn để sửa đổi tập tin cấu hình của nó.

# DBHost=localhost
DBName=test
# DBPassword=

bất kỳ đề xuất làm thế nào tôi có thể nhận được sửa đổi ở trên như dưới đây?

DBHost=localhost
DBName=database
DBPassword=password

Tôi không thể tin rằng chúng ta phải viết các biểu thức thông thường dễ bị lỗi chỉ để thực hiện công việc rất phổ biến này. Thực sự cần có một công cụ được tiêu chuẩn hóa như "update_config test.confg -uncomment_if_pressent DBHost = localhost".
bigjosh

Câu trả lời:


3

Cách tốt nhất phụ thuộc vào việc bạn mong muốn tệp cũng được sửa đổi bởi con người, mức độ phức tạp của tệp và liệu bạn có muốn tập lệnh của mình được ưu tiên nếu nó trông giống như người khác muốn có giá trị khác. Đó là, nếu tập tin đã chứa DBPassword=swordfish, bạn có muốn giữ nó, hoặc thay thế nó bằng DBPassword=password?

Một cách phổ biến để giải quyết vấn đề này là có một phần của tệp được phân định bởi các bình luận ma thuật của Cameron, và chỉ chỉnh sửa phần giữa các bình luận này. Đây là một cách để làm điều này với awk. Nếu không có bình luận ma thuật, phần mới sẽ được thêm vào cuối tập tin. Cảnh báo: mã chưa được kiểm tra.

begin_marker='# BEGIN AUTOMATICALLY EDITED PART, DO NOT EDIT'
end_marker='# END AUTOMATICALLY EDITED PART'
new_section='DBHost=localhost
DBName=database
DBPassword=password'
export begin_marker end_marker
awk <file.conf >file.conf.new -v begin_marker="$begin_marker" -v begin_marker="$end_marker" -v new_section="$new_section" '
    1 {print}
    $0 == begin_marker && !changed {
        do {getline} while ($0 != end_marker); # discard old section content
        print new_section;
        print;
        changed = 1;
    }
    END {if (!changed) {print begin_marker; print new_section; print end_marker;}}
'
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf

Cách tiếp cận này không hoạt động tốt nếu chương trình đọc tệp cấu hình không hỗ trợ nhiều dòng thiết lập cùng một mục cấu hình. Trong trường hợp đó, bạn sẽ thực sự cần phải loại bỏ những cái cũ. Trong trường hợp này, tôi sẽ khuyên bạn không để lại các bình luận và thêm cài đặt của riêng bạn vào cuối.

grep -vE '^[[:blank:]]*(DBHost|DBName|DBPassword)=$' <file.conf >file.conf.new
cat <<EOF >>file.conf.new
DBHost=localhost
DBName=database
DBPassword=password
EOF
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf

Bạn đã kiểm tra mã này? hay vẫn chưa được kiểm tra?
rubo77

Các ví dụ tuyệt vời khác tại đây: stackoverflow.com/questions/5955548/ trên
rubo77 21/07/2016

2

Nếu đó là tất cả những gì bạn cần, bạn có thể làm một cái gì đó như

sed  -i.bak -e 's/DBName=.*/DBName=database/' \
 -e 's/#* *DBHost=.*/DBHost=localhost/' \
 -e 's/#* *DBPassword=.*/DBPassword=password/' config.file

Điều này sẽ sao chép bản gốc config.fileđể config.file.bakvà thực hiện những thay đổi cần thiết.


2

Tôi sẽ đi với "ex" trong chế độ im lặng:

ex -s $CONFIG_FILE << END_CMDS
%s/^#.DBHost/DBHOST/
%s/DBName=test/DBName=database/
%s/^#.DBPassword/DBPassword/
w!
q
END_CMDS

Lệnh của terdon sednhỏ gọn và hiệu quả. Nhưng sự tương tác của một "tài liệu ở đây" có đầy đủ các lệnh ex và phép nội suy chuỗi shell có thể mạnh mẽ. Ví dụ: mật khẩu có thể được thay thế bằng giá trị của biến shell:

%s/^#.DBPassword=password/DBPassword=$PASSWORD/

Nếu bạn sử dụng vihoặc vimvà bạn quen thuộc với chế độ ':', việc thêm các chỉnh sửa mới / tốt hơn / khác nhau cũng khá dễ dàng.


Mặc dù ex rất mạnh, nhưng rất khó để phục hồi từ các lỗi (ví dụ: khi thiếu một dòng dự kiến). Ở đây bạn có thể thoát khỏi mà không có bất kỳ hành vi có điều kiện nào, nhưng điều này không khái quát quá tốt.
Gilles 'SO- ngừng trở nên xấu xa'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.