嘗試從多個文件中讀取 XML 屬性並將其替換為比以前大 1.25 倍的數字
我正在嘗試編寫一個 bash 腳本或類似的東西,我可以用它一鍵修改一堆 xml 文件中的所有出現。我有 24 個 xml 文件,每個文件包含幾十行,其中每個屬性
Torque="SOMENUMBER"
大約 3-5 次。我想用 1.25 倍的價值來替換那些,只為遊戲中的每個電機增加 25% 的扭矩。(這樣做會很有用,因為模組和遊戲更新檔會覆蓋這些,我可以快速嘗試其他值。)
我想出了
sed -n -e 's/Torque="\(.*\)"/\1/p' <filename.xml
用於提取數字的想法,將其放入變數中,然後我不知道如何將其放回正確的位置,並且sed
上面的命令同時輸出所有出現的 Torque。xmlstarlet 可能可以從我搜尋的內容中完成,但它總是抱怨包含多個根元素的 xml 文件。也許我應該以某種方式在所有內容周圍添加一個臨時標籤
<root_temp><\root_temp>
,讓 xmlstarlet 發揮它的魔力,再次刪除標籤並保存文件?已經好多年了,自從我涉足 bash 腳本,我也願意用 python、cpp 來做,學習一門新語言的基礎知識,我不在乎 xD範例 XML:
<_templates> <Engine> <RUScoutModernEngine BrakesDelay="0.5" /> </Engine> </_templates> <EngineVariants> <Engine _template="RUScoutModernEngine" CriticalDamageThreshold="0.7" DamageCapacity="120" DamagedConsumptionModifier="1.2" EngineResponsiveness="0.35" FuelConsumption="1.5" Name="ru_scout_modern_engine_0" Torque="70000" DamagedMinTorqueMultiplier="1.0" DamagedMaxTorqueMultiplier="0.6" MaxDeltaAngVel="0.01" > <GameData Price="1900" UnlockByExploration="false" UnlockByRank="1" > <UiDesc PLACE="HOLDER" /> </GameData> </Engine> <Engine BLA="BLA" Torque="80000" BLA="BLA" > <GameData Price="5500" UnlockByExploration="true" UnlockByRank="1" > <UiDesc PLACE="HOLDER" /> </GameData> </Engine> <Engine BLA="BLA" Torque="76000" BLA="BLA" > <GameData BLA="BLA" > <UiDesc/> </GameData> </Engine> </EngineVariants>
XML 片段(具有多個根節點的文件)非常難以管理,很少有工具直接接受它們。“手動”添加包裝元素是個好主意;還要注意中描述的技術
一旦你有一個格式良好的文件,在 xmlstarlet 或 Saxon 的 Gizmo ( https://saxonica.com/documentation10/index.html#!gizmo ) 中進行所需的更新應該很簡單
$$ self-interest declared $$. 在 Gizmo 中是
update //@Torque with .*1.25
在損壞的 XML 周圍添加一個假根節點很容易,修改修改後的 XML 將是輕而易舉的事
xmlstarlet
,並且在修改後刪除添加的根節點(以及添加的根節點<?xml version="1.0"?>
)xmlstarlet
也不是太難:{ echo '<root>'; cat file.xml; echo '</root>'; } | xmlstarlet ed -u '//Engine/@Torque' -x '. * 1.25' | sed '1d; 2d; $d'
這顯然假設從
{ ...; }
位中產生的 XML 實際上是格式良好的 XML 文件(您的範例文件中有重複的屬性)。與上述相同,但使用
xq
(環繞的 XML 解析器jq
,可作為https://kislyuk.github.io/yq/yq
的一部分):{ echo '<root>'; cat file.xml; echo '</root>'; } | xq -x '.root.EngineVariants.Engine[]."@Torque" |= ( tonumber * 1.25)' | sed '1d; $d'
輸出
xq
不包含.<?xml version="1.0"?>
以上述程式碼的變體為例,對
*.xml
目錄中名稱匹配的所有文件重複此操作:xmlstarlet
tmpfile=$(mktemp) for pathname in ./*.xml; do cp "$pathname" "$tmpfile" && { echo '<root>'; cat "$tmpfile"; echo '</root>'; } | xmlstarlet ed -u '//Engine/@Torque' -x '. * 1.25' | sed '1d; 2d; $d' >"$pathname" done rm -f "$tmpfile"
請注意,上面對匹配的文件進行了就地編輯。您可能想先在文件的副本上對此進行測試!