質問は次のとおりです。
データを含むxmlファイルがあり、新しいファイルに書き込むデータの小さな部分を探しています。リクエストによりコンテンツが短縮されました。
type=dhcp-client の場合、コードスニペットは次のようになります。
<deviceconfig>
<system>
<type>
<dhcp-client>
<send-hostname>yes</send-hostname>
</dhcp-client>
</type>
<hostname>Firewall</hostname>
</system>
</deviceconfig>
タイプ=静的であれば断片化
<deviceconfig>
<system>
<type>
<static/>
</type>
<hostname>Firewall</hostname>
<permitted-ip>
<entry name="192.168.0.0/24"/>
</permitted-ip>
<ip-address>192.168.0.2</ip-address>
<netmask>255.255.255.0</netmask>
<default-gateway>192.168.0.1</default-gateway>
</system>
<network>
<interface>
<ethernet>
<entry name="ethernet1/1">
<layer3>
<ip>
<entry name="192.168.0.5/24"/>
</ip>
</layer3>
</entry>
</ethernet>
</interface>
<virtual-router>
<entry name="default">
<routing-table>
<ip>
<static-route>
<entry name="default-route">
<nexthop>
<ip-address>192.168.0.1</ip-address>
</nexthop>
<interface>ethernet1/4</interface>
<destination>0.0.0.0/0</destination>
</entry>
</static-route>
</ip>
</routing-table>
</entry>
</virtual-router>
</network>
4つの関連値は、「システム」タグ内に一意または存在しません。
<system></system>
IP アドレスのようなものは、システムの外部の他の場所に再び表示されることがありますが、
<system></system>
タイプが次の場合にのみシステム内部の値を確認します。静的ではないので表示されません。 DHCPクライアントとして設定します。
タイプがdhcpの場合、必要なファイルの結果は次のとおりです。
type=dhcp-client
タイプが静的な場合、ファイルに必要な結果は次のとおりです。
type=static
ip-address=192.168.0.2
default-gateway=192.168.0.1
netmask=255.255.255.0
これを効率的に実行し、既存のシステムに統合する方法がわかりません。PHPファイルに保存します(したがって作業するには、execを使用するか、単にphpを使用することをお勧めします)。
また、Ubuntuサーバーシステムにデフォルトでインストールされているツールのみが利用可能で、他のパッケージは利用できません。
PS:これは実際には完全/完全なユースケースなので、これら2つの例外に別の出力を生成する必要はありません。助けやアドバイスをありがとうございます:)
答え1
XML認識ツールにアクセスできず、入力ファイルが表示されているように単純で規則的であると仮定すると、公開された入力例に基づいて予想される出力が生成されます。
$ cat tst.awk
BEGIN { FS="[[:space:]]*[<>][[:space:]]*"; OFS="=" }
$2 == "system" { inBlock=1 }
inBlock { f[$2] = $3 }
$2 == "/system" { inBlock=0 }
END {
if ("ip-address" in f) {
print "type", "static"
print "ip-address", f["ip-address"]
print "default-gateway", f["default-gateway"]
print "netmask", f["netmask"]
}
else {
print "type", "dhcp-client"
}
}
。
$ awk -f tst.awk absentFile
type=dhcp-client
。
$ awk -f tst.awk presentFile
type=static
ip-address=192.168.0.2
default-gateway=192.168.0.1
netmask=255.255.255.0
上記は以下の入力ファイルで実行されました。
$ tail -n +1 absentFile presentFile
==> absentFile <==
<deviceconfig>
<system>
<type>
<dhcp-client>
<send-hostname>yes</send-hostname>
</dhcp-client>
</type>
<hostname>Firewall</hostname>
</system>
</deviceconfig>
==> presentFile <==
<deviceconfig>
<system>
<type>
<static/>
</type>
<hostname>Firewall</hostname>
<permitted-ip>
<entry name="192.168.0.0/24"/>
</permitted-ip>
<ip-address>192.168.0.2</ip-address>
<netmask>255.255.255.0</netmask>
<default-gateway>192.168.0.1</default-gateway>
</system>
<network>
<interface>
<ethernet>
<entry name="ethernet1/1">
<layer3>
<ip>
<entry name="192.168.0.5/24"/>
</ip>
</layer3>
</entry>
</ethernet>
</interface>
<virtual-router>
<entry name="default">
<routing-table>
<ip>
<static-route>
<entry name="default-route">
<nexthop>
<ip-address>192.168.0.1</ip-address>
</nexthop>
<interface>ethernet1/4</interface>
<destination>0.0.0.0/0</destination>
</entry>
</static-route>
</ip>
</routing-table>
</entry>
</virtual-router>
</network>
答え2
まあ、私は直接答えを見つけました...
実際、PHPがないよりもPHPははるかに簡単です。
しかし、完成するのに時間がかかりました^^
#load the file as simplexml object and then switch into system
#https://www.w3schools.com/php/func_simplexml_load_file.asp
$xml=simplexml_load_file('./myfile') or die("Error: Cannot create object");
$xml=$xml->system
#put the whole string(s) into a variable, getname gets the name of the object itself if it exists
#https://www.w3schools.com/php/func_simplexml_getname.asp
$output='type=' . $xml -> type -> static -> getName() . $xml -> type -> {'dhcp-client'} -> getName() . "\nip-address=" . $xml -> {'ip-address'} . "\ndefault-gateway=" . $xml -> {'default-gateway'} . "\nnetmask=" . $xml -> netmask;
#write the output into a file
#https://www.w3schools.com/php/func_filesystem_file_put_contents.asp
file_put_contents('./myoutputfile', $output );
これにより、最初のスニペットに次の出力が表示されます(最後の3行に値を指定する必要はありません。そうしないと、値が最初に存在することを確認できます)。
type=dhcp-client
ip-address=
default-gateway=
netmask=
2番目のスニペットの出力:
type=static
ip-address=192.168.0.2
default-gateway=192.168.0.1
netmask=255.255.255.0
みんなの助けに感謝します:)
答え3
次のスクリプトを使用できますip-parse.sh
。
#!/bin/bash
#https://stackoverflow.com/questions/22221277/bash-grep-between-two-lines-with-specified-string
#https://www.cyberciti.biz/faq/bash-remove-whitespace-from-string/
#https://stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed
sed -n '/\<system\>/,/system\>/p' ~/Desktop/x-test.xml | sed -e 's/^[ \t]*//' > ~/Desktop/x-system.xml
sed ':a;N;$!ba;s/\n/ /g' ~/Desktop/x-system.xml > /tmp/xml-one-line.xml
#[]test to see if the "system" section ...
#... has the word hostname occuring before the word ip-address
#https://stackoverflow.com/questions/33265650/grep-for-a-string-in-a-specific-order
if [ -n "$(grep hostname.*ip-address /tmp/xml-one-line.xml)" ]; then
echo "File contains hostname and ip-address, in that order."
else
echo "type=dhcp-client" ; echo "type=dhcp-client" > ~/Desktop/network-config.txt ; exit
fi
#http://www.compciv.org/topics/bash/variables-and-substitution/
ipaddress="$(grep ip-address ~/Desktop/x-system.xml | sed 's/<ip-address>//g; s/<\/ip-address>//g')"
defaultgateway="$(grep default-gateway ~/Desktop/x-system.xml | sed 's/<default-gateway>//g; s/<\/default-gateway>//g')"
netmask="$(grep netmask ~/Desktop/x-system.xml | sed 's/<netmask>//g; s/<\/netmask>//g')"
echo "type=static" > ~/Desktop/network-config.txt
echo "ip-address=$ipaddress" >> ~/Desktop/network-config.txt
echo "default-gateway=$defaultgateway" >> ~/Desktop/network-config.txt
echo "netmask=$netmask" >> ~/Desktop/network-config.txt
適用例:
paul@mxg6:~/Desktop$ ./ip-parse.sh
File contains hostname and ip-address, in that order.
paul@mxg6:~/Desktop$ cat network-config.txt
type=static
ip-address=192.168.0.2
default-gateway=192.168.0.1
netmask=255.255.255.0
ホスト名が IP アドレスの前にあることを確認する必要がなく、中間ファイルの代わりに変数を使用する場合は、次のようにします。
#!/bin/bash
xsystemxml="$(sed -n '/\<system\>/,/system\>/p' ~/Desktop/x-test.xml \
| sed -e 's/^[ \t]*//')"
if [ -n "$(echo $xsystemxml | grep ip-address)" ]; then
echo "System section contains ip-address."
else
echo "type=dhcp-client"
echo "type=dhcp-client" > ~/Desktop/network-config.txt
exit
fi
ipaddress="$(echo "$xsystemxml" | grep "ip-address" \
| sed 's/<ip-address>//g; s/<\/ip-address>//g')"
defaultgateway="$(echo "$xsystemxml" | grep "default-gateway" \
| sed 's/<default-gateway>//g; s/<\/default-gateway>//g')"
netmask="$(echo "$xsystemxml" | grep "netmask" \
| sed 's/<netmask>//g; s/<\/netmask>//g')"
echo "type=static" > ~/Desktop/network-config.txt
echo "ip-address=$ipaddress" >> ~/Desktop/network-config.txt
echo "default-gateway=$defaultgateway" >> ~/Desktop/network-config.txt
echo "netmask=$netmask" >> ~/Desktop/network-config.txt
答え4
次の答えはhereから来ます。https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash、簡単なスクリプトを書いた
#!/bin/bash
read_dom () {
local IFS=\>
read -d \< ENTITY CONTENT
}
found=0
while read_dom; do
if [[ $ENTITY = "ip-address" ]] && [[ $last_tag = "/hostname" ]] || [[ $ENTITY = "netmask" ]] || [[ $ENTITY = "default-gateway" ]]; then
if [[ $found = 0 ]]; then
echo "type=static"
fi
echo "$ENTITY=$CONTENT"
found="1"
fi
last_tag=$ENTITY
done
if [[ $found = 0 ]]; then
echo "type=dhcp-client"
fi
スクリプト名を指定すると、parse.sh
次のように呼び出すことができます。
parse.sh < input.xml > output.txt