gpxからcsvファイルへ

gpxからcsvファイルへ
<wpt lat="1.345529841" lon="103.7577152"><time>2010-01-01T00:00:00Z</time</wpt> 
<wpt lat="1.345529841" lon="103.7577152"><time>2010-01-01T00:00:00Z</time></wpt> 
<wpt lat="1.3982529841" lon="103.90877152"><time>2010-01-01T00:00:00Z</time></wpt> 

上記の行を次に変換する必要があるファイルがあります。

         1.345529841,103.7577152,2010-01-01 00:00:00
         1.345529841,103.7577152,2010-01-01 00:00:00
         1.3982529841,103.90877152,2010-01-01 00:00:00

答え1

GPXはXML形式です。awkそのため、安定して使用したりsed解析することはできません。

代わりに、次のようなものを使用してください。XMLスター(XML文書の形式が正しくエラーがないと仮定):

$ xmlstarlet sel -t -m '//wpt' \
          -v '@lat' -o ',' \
          -v '@lon' -o ',' \
          -v 'time' -nl data.gpx
1.345529841,103.7577152,2010-01-01T00:00:00Z
1.345529841,103.7577152,2010-01-01T00:00:00Z
1.3982529841,103.90877152,2010-01-01T00:00:00Z

または:

xmlstarlet sel -t -m '//wpt' -v 'concat(@lat, ",", @lon, ",", time)' -nl data.wpx

以下を使用することもできますxq(部分的yqhttps://kislyuk.github.io/yq/):

$ xq -r '.. | .wpt? // empty | .[] | map(values) | @csv' data.gpx
"1.345529841","103.7577152","2010-01-01T00:00:00Z"
"1.345529841","103.7577152","2010-01-01T00:00:00Z"
"1.3982529841","103.90877152","2010-01-01T00:00:00Z"

その後、すべてのノードを見つけ、wptすべての属性と子ノードの値を抽出し、それからCSV出力を生成します。

列を並べ替える必要がある場合、または各列に使用する値を選択する必要がある場合でも、これを行うことができます。

$ xq -r '.. | .wpt? // empty | .[] | [."@lat", ."@lon", .time] | @csv' data.gpx
"1.345529841","103.7577152","2010-01-01T00:00:00Z"
"1.345529841","103.7577152","2010-01-01T00:00:00Z"
"1.3982529841","103.90877152","2010-01-01T00:00:00Z"

答え2

してください -awkなどの正規表現ベースのソリューションを使用しないでくださいsed

XML状況によって異なりますが、正規表現はそうではありません。そのため、うまく動作しないので、せいぜいいくつかのハッキングだけです。

ただし、XMLにはこの問題に対する解決策があります。これxpathにより、状況に応じて「検索」できます。

あなたの例を見てください:

#!/usr/bin/perl

use warnings;
use strict;
use XML::Twig;

my $xml = XML::Twig -> new -> parsefile('your_file.xml'); 

foreach my $wpt ( $xml -> get_xpath('//wpt') ) {
   print join ",", $wpt -> att('lat'), 
                   $wpt -> att('lon'),
                   $wpt -> first_child_text('time'), "\n";
}

これは望ましい結果を提供しますが、完全に有効で意味的に同じさまざまな形式のXMLも処理します。

インデントと同様に:

<xml>
  <wpt lat="1.345529841" lon="103.7577152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
  <wpt lat="1.345529841" lon="103.7577152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
  <wpt lat="1.3982529841" lon="103.90877152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
</xml>

1行にすべて:

<xml><wpt lat="1.345529841" lon="103.7577152"><time>2010-01-01T00:00:00Z</time></wpt><wpt lat="1.345529841" lon="103.7577152"><time>2010-01-01T00:00:00Z</time></wpt><wpt lat="1.3982529841" lon="103.90877152"><time>2010-01-01T00:00:00Z</time></wpt></xml>

別のインデントスタイル:

<xml>
  <wpt
      lat="1.345529841"
      lon="103.7577152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
  <wpt
      lat="1.345529841"
      lon="103.7577152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
  <wpt
      lat="1.3982529841"
      lon="103.90877152">
    <time>2010-01-01T00:00:00Z</time>
  </wpt>
</xml>

でも:

<xml
><wpt
lat="1.345529841"
lon="103.7577152"
><time
>2010-01-01T00:00:00Z</time></wpt><wpt
lat="1.345529841"
lon="103.7577152"
><time
>2010-01-01T00:00:00Z</time></wpt><wpt
lat="1.3982529841"
lon="103.90877152"
><time
>2010-01-01T00:00:00Z</time></wpt></xml>

これらは意味上すべて同じで、しなければならない同じ方法で解析します。これを行う正規表現は、XMLパーサーを使用するよりもはるかに複雑であることが誰にとっても明らかになることを願っています。

しかし、簡単に説明すると、次のようになります。

perl -MXML::Twig -0777 -e 'XML::Twig->new(twig_handlers=>{wpt=>sub{print join ",", $_->att("lat", $_->att("lon"),$_->first_child_text("time"), "\n" }})->parse(<>)'

答え3

以下を使用して、不要な文字を削除できますsed

sed 's/[^0-9.T:-]\+/,/g;s/T/ /;s/^,\|,$//g' file

s/[^0-9.T:-]\+/,/g不要な文字をカンマに置き換える

s/T/ /T文字は空白に置き換えられます。

s/^,\|,$//g最初と最後のカンマを削除

答え4

f.xml入力(有効なxml)を想定すると、次のようになります。

$ perl -MXML::DT -E 'dt("f.xml",
                         time=>sub{$a=father;
                                   $c =~ s/[TZ]/ /g;
                                   say "$a->{lat},$a->{lon},$c"}
                       )'
  • -MXML::DTXML :: DTモジュールのロード(xmlダウンコンバータ)
  • dt( file, time => sub{....})time: ファイルを解析し、そのサブファイルが実行されるのを見るたびに
  • $a=father :父から属性を取得する
  • $c:現在の要素コンテンツです。

cpan XML::DT警告:私はXML::DT(以下を使用してインストールされます)の作成者の一人です。

関連情報