Shell을 사용하여 KML에서 해수면 기압 추출

Shell을 사용하여 KML에서 해수면 기압 추출

<Placemark>저는 현재 Weatherdata.kml이라는 kml 파일에서 소규모 프로젝트를 진행 중입니다 . 각 요소에 대한 해수면 기압을 추출하고 싶습니다 . 저는 해수면 기압에 대한 정보를 구문 분석하여 다음 report.csv과 같은 파일에 넣으려고 합니다. 그리고 매번 새로운 라인에 해수면 압력을 인쇄합니다.

나는 이것이 효과가 있을 것이라고 생각합니다 awk. 지금까지 시도한 것은 다음과 같습니다.

 awk -F '[>,]' '/minSeaLevelPres/ {print $2}' report.csv

그러나 쉘에서 이 명령을 실행하면 다음과 같은 결과가 나타납니다.

1002</minSeaLevelPres
1002</minSeaLevelPres
1002</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1001</minSeaLevelPres
1002</minSeaLevelPres
1002</minSeaLevelPres
1003</minSeaLevelPres

내가 이것을 얻고 싶을 때:

1002
1002
1002
1001
1001
1001
1001
1001
1001
1001
1001
1002
1002
1003

나는 그것을 제거하는 방법을 모른다 </minSeaLevelPres. 누구든지 도와줄 수 있나요?

다음은 랜드마크 요소의 일부 예입니다.weatherdata.kml

 <Placemark>
        <styleUrl>#ex</styleUrl>
        <lat>19.2</lat>
        <lon>-24.1</lon>
        <stormName>NINE</stormName>
    <stormNum>10</stormNum>
    <basin>AL</basin>
        <stormType>LO</stormType>
        <intensity>20</intensity>
           <intensityMPH>23</intensityMPH>
           <intensityKPH>37</intensityKPH>
           <minSeaLevelPres>1002</minSeaLevelPres>
           <atcfdtg>2020082350</atcfdtg>
        <dtg>0000 UTC JAN 07</dtg>
       </Placemark>

답변1

XML을 올바르게 처리할 수 있는 도구를 사용하는 것이 좋습니다.

xmlstarlet select --template --value-of '//minSeaLevelPres' -n weatherdata.kml

산출:

1002

바라보다:xmlstarlet select --help

답변2

KML은 XML 언어입니다. XML은 안정적으로 구문 분석할 수 있는 언어가 아닙니다 awk. 가지고 있는 파일이 운이 좋을 수도 있습니다. 해당 파일의 구조는 언어 정의가 허용하는 것보다 더 안정적일 수 있습니다. 하지만 다른 도구와 일관되게 작동하는 파일을 얻으면 AWK 장치에서 제한된 구문 분석을 직접 작성할 이유가 없습니다. 예를 들어 줄 바꿈, 주석이 제거되거나 추가되면 콘텐츠가 손상됩니다.

내 생각엔 당신이 잘못된 도구를 사용하려고 하는 것 같아요. 아마도 awk시스템에 XML 파서가 설치되어 있을 것이고 pythonPython의 표준 라이브러리 이외의 외부 코드 없이 CSV를 작성하는 아주 작은 프로그램을 작성할 수 있습니다. (UNIX 철학은 "망치를 가지고 있고 이제는 모든 것이 못이다"가 아니라 "다른 목적을 위한 도구가 있으므로 목적에 맞는 도구를 찾으십시오"라는 것을 기억하십시오.)

import sys
import xml.etree.ElementTree as ElemTree

fname = sys.argv[1]
tree = ElemTree.parse(fname)
for placemark in tree.getroot().iter("Placemark"):
    print(placemark.find("minSeaLevelPres").text)

그게 다야. 파일에 저장하고 파일 실행 권한( chmod o+x {filename})을 부여한 후 실행합니다 /path/to/filename input.kml.

일반 지침:

Weatherdata.kml은 용량이 큰 파일이기 때문에,

"큰" 것이 무엇인지는 모르겠지만 수백만 개의 행이 포함된 CSV를 작성하게 되면 데이터를 매우 효율적으로 표현하지 못할 것입니다. 이 데이터의 소비자가 어떤 바이너리 형식을 지원하는지 알아보고 직접 작성하세요. 아마도 이를 달성할 수 있는 Python 라이브러리가 있을 것입니다.

답변3

awk다른 사람들과 마찬가지로 XML을 사용하고 있기 때문에 나는 이것을 권장하지 않습니다 . 그러나 어떤 이유로든 이 명령을 사용하고 싶고 파일이 작동하는 형식으로 포맷되어 있거나 awk일반 텍스트 파일이라면 더 나은 형식으로 되어 있다면 질문에서 작동하지 않습니다라는 질문에 이 명령이 있는 이유를 정확히 설명하겠습니다. :

명령 에는 >또는 에 ,표시된 필드 구분 기호가 있습니다.[>,]

awk -F '[>,]' '/minSeaLevelPres/ {print $2}' report.csv

즉, 두 번째 필드는 파일에 있는 두 문자 중 첫 번째 인스턴스 뒤에 오는 필드이며 >문자열이 포함된 줄에서 minSeaLevelPres얻을 {print $2}수 있는 내용을 정확하게 제공합니다.

1002</minSeaLevelPres>

이 특정한 경우에 제공한 예제 텍스트에서 내용을 얻으려면 1002다음이 필요합니다.

awk -F '[><]' '/minSeaLevelPres/ {print $3}' weatherdata.kml

그러면 필드 구분 기호가 >또는 로 설정되어 위 명령에서 세 번째 필드 만 인쇄되어 원하는 결과를 얻을 수 있습니다 <.10021002

1002

다시 말하지만, XML이나 논쟁의 목적으로 HTML 파일에서 사용하는 것을 권장하지 않습니다 awk. 하지만 명령이 작동하지 않는 이유와 다음과 같은 경우 명령이 작동하게 하는 방법을 설명하기 위해 이 답변을 제공할 뿐입니다. 일반 텍스트 파일에서 작동 중입니다. awk향후 이용시 참고하시면 됩니다.

답변4

사용행복하다(이전 Perl_6)

~$ raku -MXML -e 'my $xml=open-xml($*ARGFILES.Str); 
        .put for $xml.lookfor(:TAG<minSeaLevelPres>)>>.[0];' weatherdata.kml

위 내용은 Perl 계열의 프로그래밍 언어인 Raku로 작성된 답변입니다. XML명령줄 플래그를 사용하여 명령줄에서 Raku 모듈을 로드 할 수 있습니다 -MXML. 그런 다음 lookfor(재귀 요소 검색) 명령을 사용하여 XML을 구문 분석합니다. 마지막 단계 >>.[0].map(*.[0])라벨 매핑에서는 그 안에 포함된 값만 반환됩니다.

weatherdata.kml파일에 단순 위치 표시, 부동 위치 표시 또는 돌출 위치 표시 중 하나 또는 모두가 있는지 여부에 관계없이 파일이 실제로 어떻게 보이는지는 명확하지 않습니다 . 위 명령은 단순히 :TAG<minSeaLevelPres>재귀적으로 검색하여 한 줄에 하나의 값을 출력합니다.

입력 예는 다음을 참조하세요.

https://developers.google.com/kml/documentation/KML_Samples.kml

출력 예( TAG위를 테스트로 변경 :TAG<tessellate>):

1
0
1
1
1
1
1
1
1
1

https://github.com/raku-community-modules/XML
https://raku.org/

관련 정보