Linuxでgrepまたはawkを使用してxmlの文字列から値を抽出する方法

Linuxでgrepまたはawkを使用してxmlの文字列から値を抽出する方法

以下を含むファイルがあります。

DEVICE="7" PGMNR="24" VCONF="800"

このファイルからPGMNR="24""

PGMNR="24"行のどこにでも配置できます。行の開始、中間、または終了です。

この値を取得する方法がわかりません。

コメントのXMLの例:

<?xml version="1.0" encoding="utf-8"?>
<NT3Config>
  <System
      Dev="7"
      PGMNR="24"
      VCONF="800 800"
  />
  <WA-NT
      info="23 1 1 1 61 17 00"
      name="Soja T#1"
  />
  <WA-NT
      info="23 2 2 1 61 17 00"
      name="MatadorM"
  />
  <SCALE
      AdNr="0"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <SCALE
      AdNr="1"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <SCALE
      AdNr="2"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <GSM
      PIN=""
      PORT="0"
      TLF=""
  />
</NT3Config>

答え1

grepPCRE()と組み合わせて使用​​できます-P

grep -Po 'PGMNR=\"\K[^"]+(?=\")' file.txt
  • PGMNR=\"PGMNR="その部分と一致し、\K一致を削除します。

  • [^"]+番号が含まれています

  • 幅が0の順方向予測モードでは、(?=\")数字の後に"

答え2

私はパーサーを使ってこの質問に答えました。これが「正しい方法」だと思います。

これは「間違った方法」ですが、問題を解決するには最小限のPOSIXツールを使用する必要があります。

grep PGMNR $filename | sed -e 's/.*PGMNR=\"//' -e 's/\".*//'

答え3

してください - しないでください。 XMLは意味は同じですが、「パターンマッチング」が異なる多くの操作をXMLで実行できるため、正規表現および行ベースの解析ではうまく機能しません。

値を提供する式をxmlstarlet抽出できます。xpath

あるいは、私が一番好きなのは、Perlを使用してXML::TwigXMLを解析し、そのように再び必要な値を取得することです。

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a' ) ->  parse ( \*DATA );
print "PGMNR: ", $twig -> get_xpath('//System',0) -> att('PGMNR'),"\n";

__DATA__
<?xml version="1.0" encoding="utf-8"?>
<NT3Config>
<System Dev="7" PGMNR="24" VCONF="800 800" /> 
<WA-NT name="Soja T#1" info="23 1 1 1 61 17 00" />
<WA-NT name="MatadorM" info="23 2 2 1 61 17 00" />
<SCALE AdNr="0" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<SCALE AdNr="1" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<SCALE AdNr="2" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<GSM TLF="" PIN="" PORT="0" />
</NT3Config>

必要に応じて「1行」、xmlstarletXPATHを使用することもできます。

perl -0777 -MXML::Twig -e 'print XML::Twig -> parse ( <> )-> get_xpath('//System',0) -> att('PGMNR');'

注 - 正規表現ベースの解析を強くお勧めするのは、これがXMLをレンダリングするための完全に有効な方法であるためです。

<?xml version="1.0" encoding="utf-8"?>
<NT3Config>
  <System
      Dev="7"
      PGMNR="24"
      VCONF="800 800"
  />
  <WA-NT
      info="23 1 1 1 61 17 00"
      name="Soja T#1"
  />
  <WA-NT
      info="23 2 2 1 61 17 00"
      name="MatadorM"
  />
  <SCALE
      AdNr="0"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <SCALE
      AdNr="1"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <SCALE
      AdNr="2"
      Calib="0 0 0 0 0 0"
      Setting="0 0 0 0 0 0 0"
  />
  <GSM
      PIN=""
      PORT="0"
      TLF=""
  />
</NT3Config>

これ:

<?xml version="1.0" encoding="utf-8"?>
<NT3Config
><System
Dev="7"
PGMNR="24"
VCONF="800 800"
/><WA-NT
info="23 1 1 1 61 17 00"
name="Soja T#1"
/><WA-NT
info="23 2 2 1 61 17 00"
name="MatadorM"
/><SCALE
AdNr="0"
Calib="0 0 0 0 0 0"
Setting="0 0 0 0 0 0 0"
/><SCALE
AdNr="1"
Calib="0 0 0 0 0 0"
Setting="0 0 0 0 0 0 0"
/><SCALE
AdNr="2"
Calib="0 0 0 0 0 0"
Setting="0 0 0 0 0 0 0"
/><GSM
PIN=""
PORT="0"
TLF=""
/></NT3Config>

これ:

<?xml version="1.0" encoding="utf-8"?>
<NT3Config><System Dev="7" PGMNR="24" VCONF="800 800"/><WA-NT info="23 1 1 1 61 17 00" name="Soja T#1"/><WA-NT info="23 2 2 1 61 17 00" name="MatadorM"/><SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><GSM PIN="" PORT="0" TLF=""/></NT3Config>

これ:

<?xml version="1.0" encoding="utf-8"?>
<NT3Config>
  <System Dev="7" PGMNR="24" VCONF="800 800"/>
  <WA-NT info="23 1 1 1 61 17 00" name="Soja T#1"/>
  <WA-NT info="23 2 2 1 61 17 00" name="MatadorM"/>
  <SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/>
  <SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/>
  <SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/>
  <GSM PIN="" PORT="0" TLF=""/>
</NT3Config>

上記の単項タグの一部が明示的にオフになっていることも確認できます。

<System Dev="7" PGMNR="24" VCONF="800 800"/>   

そして:

<System Dev="7" PGMNR="24" VCONF="800 800"></System>

XMLに関する限り、どちらも同じことを言います。

これは、純粋にロックシステムのさらなる制約のために非常に厄介なアプローチです。しかし、上記の警告に注意してください。 XMLを解析せずにプレーンテキストを処理するので、破損しやすくなります。 (脆弱なコードはシステム管理者の気分を傷つけます。)

#!/usr/bin/env perl

use strict;
use warnings;

local $/;
my ( $PGMNR ) = <DATA> =~ m/PGMNR=\"(\d+)\"/; 
print $PGMNR;

__DATA__
<?xml version="1.0" encoding="utf-8"?>
<NT3Config>
<System Dev="7" PGMNR="24" VCONF="800 800" /> 
<WA-NT name="Soja T#1" info="23 1 1 1 61 17 00" />
<WA-NT name="MatadorM" info="23 2 2 1 61 17 00" />
<SCALE AdNr="0" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<SCALE AdNr="1" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<SCALE AdNr="2" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" />
<GSM TLF="" PIN="" PORT="0" />
</NT3Config>

またはPerlでonelinerを作成します。

perl -0777 -e 'print <> =~ m/PGMNR=\"(\d+)\"/;'

関連情報