使用shell讀取ini文件方法步驟
動機(jī)
我決定編寫一個腳本來進(jìn)行干凈的 macOS (BSD) / Linux 的初始設(shè)置。 我認(rèn)為有一個 tsukkomi 說“現(xiàn)在大多數(shù)發(fā)行版都預(yù)裝了 perl / python”,但我決定使用 Shell 腳本(bash),因?yàn)樗子诰帉戇M(jìn)程過程。 但是,用shell語法寫各種配置文件是不可讀的,所以我決定把配置文件寫成.ini文件,用sed處理,然后加載到shell中。 關(guān)于使用 sed 解析 .ini 文件,如果你在 google 上搜索會出現(xiàn)各種示例,但我決定將其作為可以處理 .ini 文件(如)的規(guī)范,通過引用它們更具可讀性。
.ini 類文件格式
- 在 [section] 中設(shè)置節(jié)。緊接在 [和緊接之前] 之后的空白字符序列(空格 / 制表符)不被視為部分名稱的一部分。 (規(guī)定可以在節(jié)名及其前后的括號之間放置空格字符。)但是,節(jié)名不應(yīng)包含換行符。
- 用 parameter = value 設(shè)置參數(shù)變量及其值。 = 前后可以有空格。假設(shè)參數(shù)名稱不包括=。如果參數(shù)名稱包含不能在 shell 變量中使用的字符,則在輸出的 shell 變量名稱中將這些字符替換為 _。
- 如果行尾有 \,則下一行被視為續(xù)行。如果一行的開頭有 4 個或更多空格/制表符,則將其視為上一行的續(xù)行。
- 忽略 # ,; 中的行尾作為注釋。
- 忽略不包含 [and’]’ 的行,或在行首以外的位置不包含 = 的行。
在 shell 腳本中處理 .ini 文件時要執(zhí)行的操作
查看部分列表。
將參數(shù)作為 shell 變量讀取。 然而,作為一種變體
1. 讓特定部分的參數(shù)為 shell 變量。 在某些情況下,將其設(shè)置為 shell 函數(shù)中的局部變量或環(huán)境變量。
2. 讓所有或部分部分的參數(shù)為 shell 變量。 shell變量名是’基于段名的前綴’+‘參數(shù)名’。 同樣在這種情況下,將其設(shè)置為局部變量或環(huán)境變量。 基于節(jié)名的前綴是通過將節(jié)名字符串中的shell變量中不能使用的字符替換為_并在末尾添加_來生成的。
假定處理系統(tǒng)
- bash
- BSD sed(我不能使用方便的 GNU sed 擴(kuò)展,但我想在干凈的 macOS 上運(yùn)行它。)但是,我使用帶有 -E 選項(xiàng)的擴(kuò)展正則表達(dá)式。 (因?yàn)槿绻荒苁褂靡粋€或多個匹配元字符’+',sed 語句就會變長。)
處理連續(xù)行和注釋似乎有更普遍的用途,所以我單獨(dú)描述。 通過將代碼添加到那里描述的 sample5.sed 來實(shí)現(xiàn)上述內(nèi)容。
查看部分列表
這相對容易。 不要處理與節(jié)名格式不匹配的行。 您所要做的就是刪除與節(jié)名格式和輸出相對應(yīng)的行中的’[‘,’]’ 和不必要的部分。 這時候需要注意的是,換行符不是隨便刪的,如單獨(dú)描述的,匹配換行符以外的表達(dá)式([^ \ [:space:]]] | [[ : 空白: ]]) 被使用。
:begin $!N s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/ s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/ $s/[#;]([^[:space:]]|[[:blank:]])*$// /(\\\n|\n[[:blank:]]{4})/ { s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ / t begin } /^[[:blank:]]*\n/ D /\n[[:blank:]]*$/ { s/\n[[:blank:]]*$// t begin } /^\[([^[:space:]]|[[:blank:]])*\]/! D s/\[[[:blank:]]*// s/[[:blank:]]*\]([^[:space:]]|[[:blank:]])*// P D
例如,如果您嘗試將其作為示例 .ini 文件,
# -*- mode: conf-mode ; -*- \ #; #; sample .ini file #; #; [tako] param_a=(1 # 2 3 \ 4 5 ### 6 7? ? ? 8 9 # 10 ? ? ) a=b # kani \ # kani \ [kani] param_a=1 param_b=2 [uni] param_a=3 param_b=4 [wani] param_a=5 param_b=6 [hebi] param_a=9 param_b=10 output example: % sed -nE -f list_section.sed sample.ini tako kani uni wani hebi
僅提取特定部分
下面的示例僅從上面的示例中提取特定部分 (wani) 的行,這些行遵循正確的參數(shù)定義格式。如果您找到以節(jié)名形式存在的一行,請將節(jié)名存儲在保留空間中,否則如果保留空間的內(nèi)容與所需的節(jié)名不匹配,則轉(zhuǎn)到下一行。…如果匹配,則檢查是否匹配參數(shù)格式的定義,去掉空格,本例中添加文本,使其成為shell函數(shù)的局部變量,可以總結(jié)shell變量定義。在行尾。因?yàn)橐呀?jīng)變長了,所以加了注釋行,但是作為控制結(jié)構(gòu),對每個處理都進(jìn)行必要的處理,如果后面的處理沒有必要,就直接回到開頭. , 應(yīng)該比較容易理解。
:begin $!N # Erase comment strings s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/ s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/ $s/[#;]([^[:space:]]|[[:blank:]])*$// # Concatenate continuation lines /(\\\n|\n[[:blank:]]{4})/ { ? s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ / ? t begin } # Erase blank lines /^[[:blank:]]*\n/ D /\n[[:blank:]]*$/ { ? s/\n[[:blank:]]*$// ? t begin } # Check section headline and store section name to holdspace /^([^[:space:]]|[[:blank:]])*\[([^[:space:]]|[[:blank:]])*\]/ { h x s/^([^[:space:]]|[[:blank:]])*\[(([^[:space:]]|[[:blank:]])*)\].*$/\2/g s/^[[:blank:]]*//g s/[[:blank:]]$//g x D } # Skip line if current section is not interested one x /^wani$/! {? ? x ? D } x # Print if it is proper parameter definition? /^(([^[:space:]=]|[[:blank:]])*)=(([^[:space:]]|[[:blank:]])*)/ { ? s/^[[:blank:]]*/local / ? s/[[:blank:]]*=[[:blank:]]*/=/ ? s/(([^[:space:]]|[[:blank:]])*)[[:blank:]]*(\n)/\1;\3/ ? P } D
如何限定 shell 變量名
如關(guān)于您想要做什么的部分中所述,您想要添加從部分名稱生成的前綴到 shell 變量,或者如果 .ini 文件中的參數(shù)名稱包含不能在 shell 變量中使用的字符串, 適當(dāng)轉(zhuǎn)換。 作為一種簡單的方法,有多次調(diào)用sed并處理的方法,但是如果可以的話,我覺得用一個進(jìn)程號sed就可以處理更漂亮。 這里最大的限制是 sed 沒有一個保存空間。 在高級腳本語言中,可以將文本段劃分為多個變量,進(jìn)行存儲、處理和組合。 另一方面,在 sed 的情況下,標(biāo)準(zhǔn)方法似乎是將多個文本作為堆棧保存和使用,并將保留空間作為分隔符并帶有換行符。
例如,在下面的示例中,保留空間從第一行開始。
- 部分名稱
- 帶格式化部分名稱的前綴
- 模式空間第一行的備份
- 模式空間第二行的備份
- 根據(jù).ini文件中的參數(shù)名格式化的Shell變量名
需要決定如何使用它,保持保持空間中的行數(shù)不變(下例中為 2 行),并在處理行轉(zhuǎn)換時適當(dāng)恢復(fù)模式空間。 由于交換保持空間和模式空間的命令只有g(shù)G和hH,類似的處理可能會重復(fù)出現(xiàn),所以不可否認(rèn)在1sed的過程中做起來真的很漂亮。
不管怎樣,下面是從上面的 sample.ini 文件中提取 wani 和 uni 部分并輸出添加了部分名稱的 shell 變量的定義語句的示例。 整體控制結(jié)構(gòu)保持簡單,并且我添加了注釋,所以我希望你能看到重寫的地方以提取另一個部分,例如。
# Initialine the hold space: (Single empty line at the beginning) 1 { H ; x ;? ? # Change the expression for the defalut section name and/or variable prefix, here. ? s/^([^[:space:]]|[[:blank:]])*(\n)([^[:space:]]|[[:blank:]])*$/global\2global_/g ? x } :begin $!N # Erase comment strings s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/ s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/ $s/[#;]([^[:space:]]|[[:blank:]])*$// # Concatenate continuation lines /(\\\n|\n[[:blank:]]{4})/ { ? s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ / ; t begin } # Erase blank lines /^[[:blank:]]*\n/ D /\n[[:blank:]]*$/ { ? s/\n[[:blank:]]*$// ; t begin } # Check section headline and store section name to holdspace /^([^[:space:]]|[[:blank:]])*\[([^[:space:]]|[[:blank:]])*\]/ { ? # Remove blackets and extra spaces at first line ? s/^([^[:space:]]|[[:blank:]])*\[(([^[:space:]]|[[:blank:]])*)\](([^[:space:]]|[[:blank:]])*)(\n)/\2\6/g ? s/^[[:blank:]]*//g; s/[[:blank:]]*(\n)/\1/g ? # Store the section name to the hold space, and format stored one for shell variable for the hold space ? h ? x ? s/(\n)([^[:space:]]|[[:blank:]])*$// ? s/([^[:alnum:]_]|$)/_/g ? x ? # Append the section name to the hold space. ? H ? # Remove unused line of the hold space and rearrange the remaining lines. ? x ? s/(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)$/\4\3\1/ ? x ? D } # Skip line if current section is not interested one x /^(wani|uni)(\n)/! { x ; D ; } x # Print if it is proper parameter definition? /^(([^[:space:]=]|[[:blank:]])*)=(([^[:space:]]|[[:blank:]])*)/ { ? # Store current patern space text at the end of the hold space ? H ? # Build shell script variable name and store it at the end of the hold space ? s/(([^[:space:]=]|[[:blank:]])*)=.*$/\1/g ? s/^[[:blank:]]*// ? s/[[:blank:]]*$// ? s/[^[:alnum:]_]/_/g ? # If further rename of the variable name is necessary, put here. ? # Store variable name at the end of the hold space ? H ? # Build parameter variable value and keep it at pattern space ? # At first, Resore the current line text from hold space ? g ? # Remove unused lines. ? s/^(([^[:space:]]|[[:blank:]])*\n){2}// ? s/(\n([^[:space:]]|[[:blank:]])*){2}$// ? # Remove the text other than the parameter value ? s/^([^[:space:]=]|[[:blank:]])*=//g ? # If further formatting of the value is necessary, put here. ? # Append hold space stored date into pattern space ? G ? # Remove unused lines from the pattern space ? s/^(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)/\1\5\9/ ? # Rearrance the order of line in the pattern space, it is nessacery because only \1 ...\9 is avaiable ? s/^(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)$/\1\3\8\7\5/ ? # Format the output in the first line of the pattern space, and? ? # Restore the next line at the second line of the pattern space ? s/^(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n([^[:space:]]|[[:blank:]])*)$/local \4\7=\1;\9/ ? # Clean up hold space ? x ? s/(\n([^[:space:]]|[[:blank:]])*){3}$// ? x ? P } D
output example:
% sed -n -E -f pickup_section2.sed sample.ini
local uni_param_a=3;
local uni_param_b=4;
local wani_param_a=5;
local wani_param_b=6;
Shell scripting
每次更改要提取的section或者切換輸出格式(sh/csh、shell變量/局部變量/環(huán)境變量、變量名前綴的ON/OFF)都要重寫sed文件很麻煩,所以命令行我準(zhǔn)備了生成 sed 命令作為選項(xiàng)的 shell 腳本。 使用另一篇文章中的模板生成。 對于上面的seds,我還嘗試了通過.ini文件的參數(shù)變量名(shell變量名)來選擇輸出。 (但是,如果指定了多個段名和變量名,組合不是唯一的,所以它可能不是一個很有用的功能。)
文件存儲:
https://github.com/nanigashi-uji/parse_ini_sh
https://gitlab.com/nanigashi_uji/parse_ini_sh
如何使用
[Usage] % parse_ini.sh -list ? ? file [files ...] ? ? ? ? % parse_ini.sh [options] file [files ...] [Options] ? ? -l,--list ? ? ? ? ? ? ? ? ? ? ? : List sections? ? ? -S,--sec-select ? ? ? name ? ? ?: Section name to select ? ? -T,--sec-select-regex expr ? ? ?: Section reg. expr. to select ? ? -V,--variable-select name ? ? ? : variable name to select ? ? -W,--variable-select-regex expr : variable reg. expr. to select ? ? -L,--local ? ? ? ? ? ? ? ? ? ? ?: Definition as local variables (B-sh) ? ? -e,--env ? ? ? ? ? ? ? ? ? ? ? ?: Definition as enviromnental variables ? ? -q,--quot ? ? ? ? ? ? ? ? ? ? ? : Definition by quoting with double/single-quotation. ? ? -c,--csh,--tcsh ? ? ? ? ? ? ? ? : Output for csh statement (default: B-sh) ? ? -b,--bsh,--bash ? ? ? ? ? ? ? ? : Output for csh statement (default) ? ? -s,--sec-prefix ? ? ? ? ? ? ? ? : add prefix: 'sectionname_' to variable names.? ? ? -v,--verbose ? ? ? ? ? ? ? ? ? ?: Verbose messages? ? ? -h,--help ? ? ? ? ? ? ? ? ? ? ? : Show Help (this message)
output example:
% parse_ini.sh --list sample.ini
tako
kani
uni
wani
hebi% parse_ini.sh -S kani -L sample.ini
local param_a=1;
local param_b=2;% parse_ini.sh -S kani -L -s sample.ini
local kani_param_a=1;
local kani_param_b=2;% parse_ini.sh -S kani -L -e -c sample.ini
setenv param_a 1;
setenv param_b 2;% parse_ini.sh -S kani -L -e -c -q sample.ini
setenv param_a "1";
setenv param_b "2";
到此這篇關(guān)于使用shell讀取ini文件方法步驟的文章就介紹到這了,更多相關(guān)shell讀取ini文件內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。