내 문제는 다음과 비슷합니다sed - 특정 요소가 포함된 XML 노드 삭제 - Think Tank 101 - CC copyright 기반 Q&A 공유 플랫폼. 거기에 제시된 제안을 구현하려고 하루 종일 바빴지만 제대로 작동하는 것이 없어서 질문을 게시했습니다.
<folder>
Bash 스크립트에서 속성이 지정된 값과 일치하면 전체 요소를 삭제해야 합니다 . 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
펄 명령어는아니요피복재. 이것은 제가 시도한 많은 변형 중 하나일 뿐입니다. 나는 또한 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>
동기화를 위한 샘플 config.xml입니다.
답변1
-L
연결된 답변에서 / --inplace
옵션( 참조 xmlstarlet edit --help
)과 정확히 일치하는 항목을 사용하세요 .
xmlstarlet ed -L -d "//configuration/folder[@id=\"$foldername\"]" config.xml
답변2
사용 중 xq
(부분적 yq
으로https://kislyuk.github.io/yq/):
xq -x --arg id "$foldername" 'del(.configuration.folder[] | select(."@id" == $id))' config.xml
내부 편집에는 -i
또는 옵션을 사용합니다 .--in-place