使用 bash 脚本在 XML 文件中查找选项块
Use a bash script to find a block of options within an XML file
我有一个 XML 文件,其结构如下:
<?xml version="1.0" encoding="utf-8"?>
<questions>
<property name="q154">
<q154>
<Property name="intro" value="Based on the information, {{1}} is older than {{2}}"/>
<Property name="op1">
<Pstructure>
<Property name="choices">
<Value>Mary</Value>
<Value>John</Value>
<Value>Carl</Value>
</Property>
<Property name="correct-indices">
<Value>3</Value>
</Property>
<Property name="hints">
<Value>Some hint here</Value>
<Value>blah blach blah</Value>
</Property>
</Pstructure>
</Property>
<Property name="op2">
<Pstructure>
<Property name="choices">
<Value>Albert</Value>
<Value>Nicole</Value>
<Value>Lizeth</Value>
</Property>
<Property name="correct-indices">
<Value>1</Value>
</Property>
<Property name="hints">
<Value>Some hint here</Value>
<Value>blah blah blah</Value>
</Property>
</Pstructure>
</Property>
</q154>
</property>
<property name="q155">
<q155>
</Property name="intro" value="You get the idea ......."/>
</Property>
</q155>
</property>
</questions>
如您所见,有介绍性文本、一些要随时替换的变量({{1}} 和 {{2}})、选项、提示等...
我想做的是创建一个 bash 脚本来查看整个文件,如果找到“变量”{{1}} 或 {{2}},它将打印整个介绍文本以及行号,在此下方,每个特定变量可用的相应选项。
所以,脚本的输出将是这样的:
user@debian: ~/projectx$ ./myscript.sh questions01.xml
::: Finding variables and options in questions01.xml...
96: Based on the information, {{1}} is older than {{2}}
97: ...op1
99: ....choices
100: ..... Mary
101: ..... John
102: ..... Carl
113: ...op2
115: ....choices
116: ..... Albert
117: ..... Nicole
118: ..... Lizeth
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
190: The winner of the race was {{1}}
191: ...op1
193: ....choices
194: ..... Lewis Hammilton
195: ..... Valtteri Bottas
196: ..... Daniel Ricciardo
197: ..... Kimi Raikkonen
这是我目前拥有的:
for f in ""*.xml
do
echo ::: Finding variables and options in $f...
vars=$(grep -nEo ".{0,30}{{[0-9]}}.{0,30}" $f | uniq)
if [ -n "$vars" ]
then
echo "$vars"
fi
done
内容不多,但我得到了变量列表,以及一些上下文(每边 30 个字符)和行号。
如何将此变量列表传递给某个函数或方法以获取其余缺少的信息,以便获得我在上面发布的输出?
PS: 不一定非要用grep,其他方式都可以,只要打印出相同的输出即可。
编辑 1:
如果我把需求分成几个步骤,它会是这样的:
- 找到每个变量 {{1}} 或 {{2}} 并获取它所在的行号
- 打印找到变量的整个“介绍”文本
- 在该行号之后,找到下一个出现的“op1”或“op2”...取决于{{1}} {{2}}...
- 找到“opX”出现后,找到下一个“选择”
属性
- 现在,在那个“选择”块中,找到每个
标签,然后
打印其内容。
- 重复循环...
那么,输出结果就是上面所说的
使用以下行创建 shell 脚本 (myscript.sh):
#!/bin/bash
cat -n $* | perl -ne '
print "::::::::::::::::::\n$_" if /<Property name="intro"/;
print if /"op\d"/../"correct-indices"/;
' | perl -ne '
next if /<Pstructure>/ || m{</Property>} || /"correct-indices">/;
s/"intro"\s+value="//;
s/"(op\d+)">//;
s/<Property name=//;
s/"choices">/choices/;
s{<value>}{}i;
s{</value>}{}i;
s{"/>}{};
print;
' | perl -ne '
s/\s+(.+?\{\{\d\}\}.+)//;
s/\s+(op\d)/.../;
s/\s+choices/....choices/;
s/^\s+(.+?)/...../;
print;
' | perl -pe '
s/^(\.+?)(\d+)\t\s+/: /;
s/\t\s+/: /;
s/^\.+(\d+)(\.+?)/: /;'
执行它./myscript.sh questions01.xml
将导致
::::::::::::::::::
5: Based on the information, {{1}} is older than {{2}}
6: ...op1
8: ....choices
9: .....Mary
10: .....John
11: .....Carl
22: ...op2
24: ....choices
25: .....Albert
26: .....Nicole
28: .....Lizeth
我有一个 XML 文件,其结构如下:
<?xml version="1.0" encoding="utf-8"?>
<questions>
<property name="q154">
<q154>
<Property name="intro" value="Based on the information, {{1}} is older than {{2}}"/>
<Property name="op1">
<Pstructure>
<Property name="choices">
<Value>Mary</Value>
<Value>John</Value>
<Value>Carl</Value>
</Property>
<Property name="correct-indices">
<Value>3</Value>
</Property>
<Property name="hints">
<Value>Some hint here</Value>
<Value>blah blach blah</Value>
</Property>
</Pstructure>
</Property>
<Property name="op2">
<Pstructure>
<Property name="choices">
<Value>Albert</Value>
<Value>Nicole</Value>
<Value>Lizeth</Value>
</Property>
<Property name="correct-indices">
<Value>1</Value>
</Property>
<Property name="hints">
<Value>Some hint here</Value>
<Value>blah blah blah</Value>
</Property>
</Pstructure>
</Property>
</q154>
</property>
<property name="q155">
<q155>
</Property name="intro" value="You get the idea ......."/>
</Property>
</q155>
</property>
</questions>
如您所见,有介绍性文本、一些要随时替换的变量({{1}} 和 {{2}})、选项、提示等...
我想做的是创建一个 bash 脚本来查看整个文件,如果找到“变量”{{1}} 或 {{2}},它将打印整个介绍文本以及行号,在此下方,每个特定变量可用的相应选项。
所以,脚本的输出将是这样的:
user@debian: ~/projectx$ ./myscript.sh questions01.xml
::: Finding variables and options in questions01.xml...
96: Based on the information, {{1}} is older than {{2}}
97: ...op1
99: ....choices
100: ..... Mary
101: ..... John
102: ..... Carl
113: ...op2
115: ....choices
116: ..... Albert
117: ..... Nicole
118: ..... Lizeth
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
190: The winner of the race was {{1}}
191: ...op1
193: ....choices
194: ..... Lewis Hammilton
195: ..... Valtteri Bottas
196: ..... Daniel Ricciardo
197: ..... Kimi Raikkonen
这是我目前拥有的:
for f in ""*.xml
do
echo ::: Finding variables and options in $f...
vars=$(grep -nEo ".{0,30}{{[0-9]}}.{0,30}" $f | uniq)
if [ -n "$vars" ]
then
echo "$vars"
fi
done
内容不多,但我得到了变量列表,以及一些上下文(每边 30 个字符)和行号。
如何将此变量列表传递给某个函数或方法以获取其余缺少的信息,以便获得我在上面发布的输出?
PS: 不一定非要用grep,其他方式都可以,只要打印出相同的输出即可。
编辑 1: 如果我把需求分成几个步骤,它会是这样的:
- 找到每个变量 {{1}} 或 {{2}} 并获取它所在的行号
- 打印找到变量的整个“介绍”文本
- 在该行号之后,找到下一个出现的“op1”或“op2”...取决于{{1}} {{2}}...
- 找到“opX”出现后,找到下一个“选择” 属性
- 现在,在那个“选择”块中,找到每个
标签,然后 打印其内容。 - 重复循环...
那么,输出结果就是上面所说的
使用以下行创建 shell 脚本 (myscript.sh):
#!/bin/bash
cat -n $* | perl -ne '
print "::::::::::::::::::\n$_" if /<Property name="intro"/;
print if /"op\d"/../"correct-indices"/;
' | perl -ne '
next if /<Pstructure>/ || m{</Property>} || /"correct-indices">/;
s/"intro"\s+value="//;
s/"(op\d+)">//;
s/<Property name=//;
s/"choices">/choices/;
s{<value>}{}i;
s{</value>}{}i;
s{"/>}{};
print;
' | perl -ne '
s/\s+(.+?\{\{\d\}\}.+)//;
s/\s+(op\d)/.../;
s/\s+choices/....choices/;
s/^\s+(.+?)/...../;
print;
' | perl -pe '
s/^(\.+?)(\d+)\t\s+/: /;
s/\t\s+/: /;
s/^\.+(\d+)(\.+?)/: /;'
执行它./myscript.sh questions01.xml
将导致
::::::::::::::::::
5: Based on the information, {{1}} is older than {{2}}
6: ...op1
8: ....choices
9: .....Mary
10: .....John
11: .....Carl
22: ...op2
24: ....choices
25: .....Albert
26: .....Nicole
28: .....Lizeth