任务:
我正在尝试使用shell脚本从xml标记获取属性值,将值拆分并将其保存在.csv文件中。
这就是xml的样子:
<host>
<servers>
<server name="Type1Name1-Port1" >...</server>
<server name="Type2Name2-Port2" >...</server>
<server name="Type3Name3-Port3" >...</server>
...
<server name="TypexNamex-Portx" >...</server>
</servers>
</host>
我想从“名称” - 属性中获取值并将它们拆分如下:
Type;Name;Port
我想要的输出csv文件应如下所示:
Type1;Name1;Port1
Type2;Name2;Port2
Type3;Name3;Port3
...
Typex;Namex;Portx
问题:
我可以使用我想要的任何shell语言。我更喜欢bash和ksh。
我的问题:
修改
服务器名称的示例数据:
T-TTT_AAA-A-SSS-PPPP
其中T表示类型,A表示应用程序名称,S表示服务器名称,P表示端口。 T,A和S的长度是可变的。 P是常数。
答案 0 :(得分:1)
以下是我提出的建议,仅使用常用工具:Public Property Let
和DicOption.Add key:=OptName, Item:=OptValue
:
'Userform Class Module
Private DicOption As scripting.Dictionary
Public Property Get ProjectOption(ByVal OptName As String) As String
ProjectOption = UBidStatus.ProjectOption(OptName)
End Property
Public Property Let ProjectOption(ByVal OptName As String, ByVal OptValue As String)
If Not DicOption(OptName).Exists Then
DicOption.Add key:=OptName, Item:=OptValue
Else
DicOption(OptName) = OptValue
End If
End Property
Public Sub UserForm_Initialize()
Set DicOption = New scripting.Dictionary
End Sub
Private Sub UserForm_Terminate()
Set DicOption = Nothing
End Sub
Public Sub ExchangeToDicOption()
Dim LR As Long
Dim Rg As Range
Dim ws As Worksheet
Dim i As Long
Dim a As String
Dim b As String
Set ws = ActiveWorkbook.Worksheets(2)
Set Rg = ws.Columns(2)
DicOption.RemoveAll
LR = Rg.Find(What:="*", Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
If LR > 1 Then
For i = 2 To LR
a = Cells(i, 1)
b = Cells(i, 2)
UBidStatus.ProjectOption(a) = b
Next i
End If
End Sub
xmllint
部分是根据OP发布时的示例完成的。
<强>故障:强>
sed
:我们将此命令传递给echo 'cat //host/servers/server/@name' | xmllint --shell data.xml | sed -n 's: name=\"\([A-Z][a-z0-9]*\)\([A-Z][a-z0-9]*\)-\(.*\)\":\1,\2,\3:p'
。它将捕获sed
echo 'cat //host/servers/server/@name'
属性
xmllint
:遍历name
并执行在交互式shell中作为参数传递的命令。<host><servers><server ...> ... </server></servers></hosts>
:我们处理xmllint --shell data.xml
的输出只保留我们感兴趣的数据
data.xml
将生成以下输出:sed -n 's: name=\"\([A-Z][a-z0-9]*\)\([A-Z][a-z0-9]*\)-\(.*\)\":\1;\2;\3:p'
xmllint
),另一个大写字母后跟除了大写之外的任何字符(用于xmllint
),以及之间的任何字符name="Type1Name1-Port1"
和Type
字符输出:
Name
编辑:
要符合您在评论中指明的模式,您只需更改sed正则表达式,例如:
-
这将匹配格式"
,具有类型和服务器名称的任何长度。如果这不完全符合您的要求,请尽量摆弄正则表达式或在Type1;Name1;Port1
Type2;Name2;Port2
Type3;Name3;Port3
Typex;Namex;Portx
标记中提出其他问题。
答案 1 :(得分:1)
如果没有xmllint,您可以解析输入,如
<host>
<servers>
<server name="Type1_Name1-Port1" >...</server>
<server name="Type-2_Name2-Port2" >...</server>
<server name="Type3_Name-3-Port3" >...</server>
</servers>
</host>
与
sed -n '/<server name=/ s/[^"]*"\([^_]*\)_\([^"]*\)-\([^"]*\)".*/\1;\2;\3/p' inputfile
答案 2 :(得分:0)
xidel -e '//server/@name' f.xml | sed ...