ワンクリックで複数のXMLファイルのすべての一致を変更するために使用できるbashスクリプトまたは同様のスクリプトを作成しようとしています。私は24個のXMLファイルを持っていますTorque="SOMENUMBER"
。ゲーム内のすべてのモーターにトルクを25%追加するために、これを1.25倍の値に置き換えたいと思います。
(モードとゲームパッチがこれを無視して他の値をすばやく試すことができるので、これは便利です。)
数字を抽出して変数に入れるというアイデアが浮かび上がりましたがsed -n -e 's/Torque="\(.*\)"/\1/p' <filename.xml
、どうやって正しい位置に入れるのか分からず、sed
上記のコマンドは発生するすべてのトルクを一度に出力します。
xmlstarletは私がGoogleで検索したものに基づいてこれを行うことができますが、常に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>
ベストアンサー1
破損した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
使用可能です)を使用します。yq
https://kislyuk.github.io/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"
一致するファイルは上からその場所で編集されます。欲しいかもしれませんコピーまず、ファイルです!