我有一個包含內容的 txt.ini 檔案(我無法修改此檔案的結構):
組態檔
組態檔
[person_0:public]
name=john
groups=0,1,2
age=30
[person_0:private]
married=false
weight=190
height=100
[person_1:public]
name=mark
groups=0,4
age=28
[person_1:private]
married=false
weight=173
height=70
[person_2:public]
name=tony
groups=3,4
age=30
[person_3:private]
married=true
weight=202
height=120
我有一個變數“人”,它在回圈中取值之一:person_0、person_1、person_3,我想一一收集每個“人”的年齡和組等人的資料。
我的想法是剪掉 $person:public 和 $person:private 之間的部分,然后收集
例如設定變數 person=person_1 輸出:groups=0,4 age=28
我在bash中準備了代碼(persons是person_0、person_1、person2的串列):
for person in ${persons[@]}; do
file="txt.ini"
echo "$person"
a=$(awk -v a=$person":private" -v b=$person":public" '/a/{found=0} {if(found) print} /b/{found=1}' $file)
IFS=$'\n' lines=($a)
IFS='=' read grouplist grouplist_values <<< ${lines[1]}
IFS='=' read age age_values <<< ${lines[4]}
echo "Group list = $grouplist_values"
echo "Age = $age_values"
組串列和年齡為空。輸出:
person_0
Group list =
Age =
person_1
Group list =
Age =
person_2
Group list =
Age =
預期的:
person_0
Group list =0,1,2
Age =30
person_1
Group list =0,4
Age =28
person_2
Group list =3,4
Age =30
我將在我的代碼的另一部分中“每人”使用這些資料。我正在處理具有不同“人數”的檔案。
我真的不知道出了什么問題。
我也試過:
#export person="person_0"
#a=$(awk '/ENVIRON["person"]:private/{found=0} {if(found) print} /ENVIRON["person"]:public/{found=1}' $file)
和
private=$person":private"
public=$person":public"
echo "private=$private"
echo "public=$public"
a=$(awk -v a=$private" -v b=$public '/a/{found=0} {if(found) print} /b/{found=1}' $config_file)
但輸出是一樣的:
person_0
private=person_0:private
public=person_0:public
Group list =
Age =
對我來說奇怪的是 - 當我對切割范圍進行硬編碼時,它可以正常作業:
a=$(awk '/person_0:private/{found=0} {if(found) print} /person_0:public/{found=1}' $file)
或者
a=$(awk '/person_1:private/{found=0} {if(found) print} /person_1:public/{found=1}' $file)
您知道如何以巧妙的方式收集這些資料嗎?
uj5u.com熱心網友回復:
假設:
- 對于給定的人(例如,
person_0)顯示該人以及相關的(public)欄位groups和age - 沒有說明我們應該如何處理這些資料,所以假設,現在,我們只需要列印到標準輸出
- 要處理的人員串列在
bash陣列中persons[] - 字串
:public并且:private只出現在區塊頭中
awk我們使用該split()函式根據不同的分隔符決議一行的一個想法:
awk '
FNR==NR { persons[$1]
next
}
/:private/ { printme=0 }
/:public/ { printme=0
split($1,arr,"[]:[]")
person=arr[2]
if (person in persons) {
printme=1
printf "%s%s\n", pfx, person
pfx="\n"
}
}
printme { split($1,arr,"=")
if (arr[1] == "groups") print "Group list =" arr[2]
if (arr[1] == "age") print "Age =" arr[2]
}
' <(printf "%s\n" "${persons[@]}") txt.ini
此主題的變體使用多字符輸入欄位分隔符:
awk -F"[]:=[]" '
FNR==NR { persons[$1]
next
}
$3=="private" { printme=0 }
$3=="public" { printme=0
if ($2 in persons) {
printme=1
printf "%s%s\n", pfx, $2
pfx="\n"
}
}
printme && $1=="groups" { print "Group list =" $2 }
printme && $1=="age" { print "Age =" $2 }
' <(printf "%s\n" "${persons[@]}") txt.ini
和:
$ typeset -p persons
declare -a persons=([0]="person_0" [1]="person_1" [2]="person_2")
兩組awk代碼生成:
person_0
Group list =0,1,2
Age =30
person_1
Group list =0,4
Age =28
person_2
Group list =3,4
Age =30
注意:這可以變得更加動態(public和/或private?不同的欄位?)但這需要更多的編碼
uj5u.com熱心網友回復:
請您嘗試以下操作:
awk -v RS='' ' # split the records on the blank lines
/public/ { # "public" record
split($1, a, /[\[:]/); print a[2] # extract the "person_xx" substring
for (i = 2; i <= NF; i ) { # iterate over the lines of the record
split($i, a, /=/)
if (a[1] == "groups") print "Group list =" a[2]
else if (a[1] == "age") print "Age =" a[2]
}
print "" # insert a blank line
}
' txt.ini
輸出:
person_0
Group list =0,1,2
Age =30
person_1
Group list =0,4
Age =28
person_2
Group list =3,4
Age =30
- 通過將
awk變數設定RS為空字串,記錄由空行分隔,欄位由換行符分隔。 - 假設
public塊中包含了想要的資料,我們就可以public一一決議記錄的欄位。
[編輯]
根據 OP 的評論,這里是更新的版本:
#!/bin/bash
persons=("person_0") # list of desired person(s)
for person in "${persons[@]}"; do # loop over the bash array
awk -v RS='' -v person="$person" ' # assign awk variables
$1 ~ person ":public" { # "public" record of the person
split($1, a, /[\[:]/); print a[2] # extract the "person_xx" substring
for (i = 2; i <= NF; i ) { # iterate over the lines of the record
split($i, a, /=/)
if (a[1] == "groups") print "Group list =" a[2]
else if (a[1] == "age") print "Age =" a[2]
}
}
' txt.ini
echo # insert a blank line
done
- 您可以將
persons陣列分配給您想要的任何人。 - 該模式
$1 ~ person ":public"測驗記錄的第一個欄位$1(例如[person_0:public])是否匹配 awk 變數person(通過-v選項傳遞),后跟字串“:public”。
顯然,awk 腳本重復讀取txt.ini檔案的次數與persons陣列中的 #elements 一樣多。如果text.ini檔案很長和/或persons陣列有很多元素,回圈將效率低下。這是另一個變體:
#!/bin/bash
persons=("person_0" "person_1") # bash array just for an example
awk -v RS='' -v persons_list="${persons[*]}" '
# persons_list is a blank separated list of persons
BEGIN {
split(persons_list, a) # split persons_list back to an array
for (i in a) persons[a[i]] # create a new array indexed by person
}
/public/ { # "public" record
split($1, a, /[\[:]/) # extract the "person_xx" substring
if (a[2] in persons) { # if the person exists in the list
print a[2]
for (i = 2; i <= NF; i ) { # iterate over the lines of the record
split($i, a, /=/)
if (a[1] == "groups") print "Group list =" a[2]
else if (a[1] == "age") print "Age =" a[2]
}
print "" # insert a blank line
}
}
' txt.ini
請注意,它假定 person 字串不包含空格字符。如果是這樣,請在將 分配persons_list給未使用的字符(例如逗號)時更改分隔符。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/336375.html
上一篇:XamarinFormsDark/LightMode主題不適用于Android上的shell導航選項卡
下一篇:在shell腳本中呼叫鏈碼函式
