Bash

使用 xmlstarlet 刪除與屬性值匹配的整個元素?

  • May 2, 2021

我的問題類似於sed - Delete XML node contains certain element - Unix & Linux Stack Exchange。試圖實施那裡的建議讓我整天忙碌,但我沒有設法讓任何工作,所以我發布了一個問題。

在 bash 腳本中,當屬性與給定值匹配時,我需要刪除整個<folder>元素。id我實際上正在使用使用者組來完成其中的一部分。假設使用者不在組中folder_a;然後應該從 config.xml 中刪除具有屬性的整個<folder>元素。id=".Folder_A"(我也從磁碟中刪除了該文件夾。)

我的 bash 腳本如下所示:

#!/bin/bash

grouplist=$(groups $theuser);
for foldername in '.Folder_A' '.Folder_B'; do
 grpnm="${foldername,,}"|sed -e 's/^.//'
 if ! [[ $grouplist =~ ${grpnm} ]]; then
   perl -0777 -pe "s|(<folder.*?</folder>)|$1=~ /id=\"$foldername\"/?"":$1|gse" config.xml > config.xml
   rm -fr "$foldername"
 else
   echo "permitting access to ${foldername}"
 fi
done

perl 命令不起作用。它只是我嘗試過的眾多變體之一。我也試過sed。我更喜歡使用 xmlstarlet,但我遇到了更多麻煩。

編輯- 我剛剛找到了這個答案:https ://unix.stackexchange.com/a/339089/393289 它幫助我想出了這個:

xml ed -d '//configuration/folder[contains(@id,".Folder_A")]' config.xml

我覺得我現在更接近了。(我試圖支持該答案,但我還沒有足夠的代表。)但是,由於引號或其他原因,我還無法將屬性名稱轉換為 bash 變數。

sed -i順便說一句,一旦我讓它工作,我如何讓它執行就地編輯(類似於命令)?

這是一個範例 config.xml 文件:

   <?xml version="1.0"?>
   <configuration version="32">
       <folder id=".Folder_A" label=".Folder_A" path="~/Sync/.Folder_A" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
           <filesystemType>basic</filesystemType>
           <device id="123ABC" introducedBy="">
               <encryptionPassword/>
           </device>
           <device id="987ZYX" introducedBy="">
               <encryptionPassword/>
           </device>
           <minDiskFree unit="">0</minDiskFree>
           <versioning>
                   <cleanupIntervalS>0</cleanupIntervalS>
           </versioning>
           <copiers>0</copiers>
           <disableSparseFiles>false</disableSparseFiles>
           <disableTempIndexes>false</disableTempIndexes>
           <paused>false</paused>
           <weakHashThresholdPct>25</weakHashThresholdPct>
           <markerName>.stfolder</markerName>
       </folder>
       <folder id=".Folder_B" label="Corporate (.Folder_B)" path="~/Sync/.Folder_B" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="5" ignorePerms="true" autoNormalize="false">
           <filesystemType>basic</filesystemType>
           <device id="123ABC" introducedBy="">
               <encryptionPassword/>
           </device>
           <device id="987ZYX" introducedBy="">
               <encryptionPassword/>
           </device>
           <minDiskFree unit="">0</minDiskFree>
           <versioning>
                   <cleanupIntervalS>0</cleanupIntervalS>
           </versioning>
           <copiers>0</copiers>
           <disableSparseFiles>false</disableSparseFiles>
           <disableTempIndexes>false</disableTempIndexes>
           <paused>false</paused>
           <weakHashThresholdPct>25</weakHashThresholdPct>
           <markerName>.stfolder</markerName>
       </folder>
       <device id="123ABC" name="laptop" compression="always" introducer="false" skipIntroductionRemovals="false" introducedBy="">
           <paused>false</paused>
           <autoAcceptFolders>true</autoAcceptFolders>
           <maxSendKbps>0</maxSendKbps>
           <maxRecvKbps>0</maxRecvKbps>
           <maxRequestKiB>0</maxRequestKiB>
           <untrusted>false</untrusted>
       </device>
       <device id="987ZYX" name="desktop" compression="always" introducer="false" skipIntroductionRemovals="false" introducedBy="">
           <paused>false</paused>
           <autoAcceptFolders>true</autoAcceptFolders>
           <maxSendKbps>0</maxSendKbps>
           <maxRecvKbps>0</maxRecvKbps>
           <maxRequestKiB>0</maxRequestKiB>
           <untrusted>false</untrusted>
       </device>
       <gui enabled="true" tls="true" debugging="false">
           <address>127.0.0.1:8384</address>
           <apikey>98qewr0qe9r</apikey>
           <theme>default</theme>
       </gui>
       <ldap/>
       <options>
           <listenAddress></listenAddress>
           <maxSendKbps>0</maxSendKbps>
           <maxRecvKbps>0</maxRecvKbps>
           <reconnectionIntervalS>60</reconnectionIntervalS>
           <relaysEnabled>false</relaysEnabled>
           <relayReconnectIntervalM>10</relayReconnectIntervalM>
           <startBrowser>false</startBrowser>
           <urAccepted>-1</urAccepted>
           <urSeen>3</urSeen>
           <urUniqueID/>
           <urPostInsecurely>false</urPostInsecurely>
           <urInitialDelayS>1800</urInitialDelayS>
           <restartOnWakeup>true</restartOnWakeup>
           <upgradeToPreReleases>false</upgradeToPreReleases>
           <keepTemporariesH>24</keepTemporariesH>
           <cacheIgnoredFiles>false</cacheIgnoredFiles>
           <progressUpdateIntervalS>5</progressUpdateIntervalS>
           <limitBandwidthInLan>false</limitBandwidthInLan>
           <overwriteRemoteDeviceNamesOnConnect>false</overwriteRemoteDeviceNamesOnConnect>
           <tempIndexMinBlocks>10</tempIndexMinBlocks>
           <trafficClass>0</trafficClass>
           <defaultFolderPath>~/Sync/</defaultFolderPath>
           <maxFolderConcurrency>0</maxFolderConcurrency>
           <crashReportingEnabled>false</crashReportingEnabled>
           <databaseTuning>auto</databaseTuning>
           <maxConcurrentIncomingRequestKiB>0</maxConcurrentIncomingRequestKiB>
           <announceLANAddresses>false</announceLANAddresses>
           <sendFullIndexOnUpgrade>false</sendFullIndexOnUpgrade>
       </options>
   </configuration>

這是syncthing 的config.xml 範例。

使用-L/--inplace選項(請參閱xml edit --help)和連結答案中的完全匹配:

xml ed -L -d "//configuration/folder[@id=\"$foldername\"]" config.xml

使用xqyq來自https://kislyuk.github.io/yq/的一部分):

xq -x --arg id "$foldername" 'del(.configuration.folder[] | select(."@id" == $id))' config.xml

使用-ior--in-place選項進行就地編輯。

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