Bash

嘗試從多個文件中讀取 XML 屬性並將其替換為比以前大 1.25 倍的數字

  • May 6, 2021

我正在嘗試編寫一個 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 片段(具有多個根節點的文件)非常難以管理,很少有工具直接接受它們。“手動”添加包裝元素是個好主意;還要注意中描述的技術

https://stackoverflow.com/questions/23571941/making-use-of-an-xml-file-with-more-than-one-root-element/23574398#23574398

一旦你有一個格式良好的文件,在 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"

請注意,上面對匹配的文件進行了就地編輯。您可能想先在文件的副本上對此進行測試!

引用自:https://unix.stackexchange.com/questions/647960