我正在通过bash脚本生成(实际编辑)mobileconfig文件(也就是iOS配置文件,XML)。
脚本从MS数据库中获取数据,现在可以在我的mobileconfig文件(XML)中注入/替换此数据。
XML文件具有以下结构:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>Host</key>
<string>outlook.office365.com</string>
<key>MailNumberOfPastDaysToSync</key>
<integer>7</integer>
<key>Password</key>
<string>ActiveSyncPassword</string>
<key>PayloadDescription</key>
<string>Configures an Exchange account</string>
<key>PayloadDisplayName</key>
<string>Exchange ActiveSync</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>SSL</key>
<true/>
<key>UserName</key>
<string>xxxxxxx@xxx.com</string>
<key>disableMailRecentsSyncing</key>
<false/>
</dict>
<dict>
<key>AutoJoin</key>
<true/>
<key>EncryptionType</key>
<string>WPA</string>
<key>HIDDEN_NETWORK</key>
<true/>
<key>IsHotspot</key>
<false/>
<key>Password</key>
<string>WEPWPAWPSPEAPTLS</string>
<key>PayloadType</key>
<string>com.apple.wifi.managed</string>
<key>PayloadVersion</key>
<real>1</real>
<key>ProxyType</key>
<string>None</string>
<key>SSID_STR</key>
<string>SSID</string>
</dict>
<dict>
我想更换WiFi密码,还要更换ActiveSync&#34;密码&#34; &之间的字段串GT; &LT; /串GT;使用任何本机(xmllint,sed)或非本机工具。
有人可以帮忙吗?
答案 0 :(得分:3)
使用纯文本工具编辑结构化数据(例如XML),当文件格式以无人希望产生差异的方式(例如插入良性空白)的方式发生变化时,总会以痛苦结束。相反,请使用正确解析XML并在树上工作的工具,例如xmlstarlet
。
一般形式是
xmlstarlet ed -u xpath -v value filename.xml
其中xpath
是标识要更新的节点的XPath表达式,value
是您要为其提供的新值。神奇的是构建一个XPath表达式,它唯一且可靠地识别您要更新的节点。 MobileConfig XML格式使这比平常更难。在评论中讨论后我们最终得到了
xmlstarlet ed -u '//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]/key[text() = "Password"]/following-sibling::string[1]' -v 'abc123' filename.xml
这是XPath表达式
的核心//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]/key[text() = "Password"]/following-sibling::string[1]
..这需要一些解释。我们使用以下功能:
//dict
匹配文档中的任何dict
节点//dict/key
匹配key
节点子节点的任何dict
节点,//dict/key[text() = "Password"]
匹配key
节点的子节点dict
并且包含文字Password
,//dict/key[text() = "Password"]/following-sibling
匹配此类key
节点的任何后续兄弟节点,也就是说,任何节点都是同一父节点的子节点,并且位于XML中的key
节点之后,//dict/key[text() = "Password"]/following-sibling::string
匹配任何string
节点,这是以下兄弟节点,//dict/key[text() = "Password"]/following-sibling::string[1]
匹配此类string
节点的第一个兄弟key
节点之后的任何节点。我们已经在//dict/key[text() = "Password"]
中使用了一个条件;为了找到要更改其密码条目的dict
节点,我们需要更多。我们要查找的dict
节点由
//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]
这是一个满足条件的dict
节点
key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"
此条件下的XPath表达式都与正在测试的dict
节点相关,因此
key[text() = "PayloadDisplayName"]
指的是key
节点的dict
子节点,其中包含文本PayloadDisplayName
和
key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"
如果string
节点中包含文本key
的{{1}}节点后面的文本为PayloadDisplayName
,则为true。所以我们把它放到我上面解释的简化表达式中并获得完整的过滤器。
我不得不指出,这个XML文件的结构使得整个事情比必要或通常更难。可以使用更简单的XPath表达式处理Sanely结构化的XML(大多数情况下)。
答案 1 :(得分:1)
你可以这样做
sed -r "s#(<string>)SSID_STR(</string>)#\1AMD\2#g" File
对于原地替换:
sed -i -r "s#(<string>)SSID_STR(</string>)#\1AMD\2#g" File
(
,)
用于分组。 \1
和\2
代表first
和second
个此类群组。
将AMD替换为您的实际内容。同样,你可以为密码做。