<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
(부분적 yq
으로https://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>
한 줄에 모두 :
<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::DT
XML::DT 모듈 로드(xml 다운 변환기)dt( file, time => sub{....})
time
: 파일을 구문 분석하고 해당 하위 파일이 실행되는 것을 볼 때마다$a=father
: 아버지로부터 속성 가져오기$c
: 현재 요소 콘텐츠입니다.
cpan XML::DT
경고: 저는 XML::DT(다음을 사용하여 설치됨)의 작성자 중 한 명입니다.