2012-08-30 4 views
1

정규식을 사용하여 형식을 바꾸려는 (잘된 것은 아닙니다!) 올바른 형식의 XML 파일이 있습니다. 목표는 모든 <trkpt> 쌍을 oneliner로 유지하는 것입니다.패턴 일치 내에서 공백을 제거하는 Python 정규식

다음 코드는 작동하지만 루프 대신 단일 정규식 대체에서 수행 된 작업을 가져와 문자열을 다시 연결할 필요가 없습니다.

import re 

xml = """ 
    <trkseg> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"> 
     <time>2012-08-25T10:20:44Z</time> 
     <ele>0</ele> 
     </trkpt> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"> 
     <time>2012-08-25T10:20:44Z</time> 
     <ele>0</ele> 
     </trkpt> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"> 
     <time>2012-08-25T10:20:44Z</time> 
     <ele>0</ele> 
     </trkpt> 
    </trkseg> 
""" 

for trkpt in re.findall('<trkpt.*?</trkpt>', xml, re.DOTALL): 
    print re.sub('>\s*<', '><', trkpt, re.DOTALL) 

sed를 사용하는 대답도 환영받을 것입니다. 이것은 당신이 요청하지만, 여기에 한 줄 인의 이익을위한 한 줄의 있었는지 정말 아니다

+0

그것은'trkseg' 또는 한 줄로 원하는'trkpt'인가? 'trkseg'라고 말하지만 정규 표현식은'trkpt'에서 작동합니다 ... – KRyan

+0

또한 그 중 어떤 식 으로든 해당 유형의 중첩 태그를 가질 수 없다고 가정합니다. 당신이 둥지를 짓 자마자, 정규식은 그것을 처리 할 수 ​​없을 것입니다. – KRyan

+0

이것이 "빠르고 더러운"스크립트이고, XML을 구문 분석하고 싶지 않다면, for 루프는 더 간단하고 미친 정규식보다 훨씬 더 읽기 쉽다고 말할 수 있습니다. –

답변

1

이 방법에 대해 :

>>> regex = re.compile(
    r"""\n[ \t]* # Match a newline plus following whitespace 
    (?=   # only if... 
    (?:   # ...the following can be matched: 
     (?!<trkpt) # (unless an opening <trkpt> tag occurs first) 
     .   # any character 
    )*   # any number of times, 
    </trkpt>  # followed by a closing </trkpt> tag 
    )    # End of lookahead""", 
    re.DOTALL | re.VERBOSE) 
>>> print regex.sub("", xml) 

    <trkseg> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
     <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
    </trkseg> 
+0

그것은 나를 위해 처음으로 작동하지 않았다. 'regex = re.compile ('\ n [\ t] * (? = (? :(?! ) ', re.DOTALL)'. 그런 다음 효과가 있었지만 들여 쓰기를 먹었습니다 (커다란 문제는 아니며 어쨌든 결과를 미리 인쇄 할 계획 임). – heltonbiker

+0

@heltonbiker : 죄송합니다. 정규 표현식을 장황한 것으로 변경했을 때 문자열의'r' 접두어를 잊어 버렸습니다. 이제 제대로 작동해야합니다. 더 일찍 대답하지 않아서 미안하지만 당신이 당신의 코멘트를 썼을 때 자정이 지난 지금 여기 있습니다. –

1

를 읽기위한

감사 : 또한

>>> print re.sub(r'(<trkpt.*?</trkpt>)', 
       lambda m: re.sub(r'>\s*<', '><', m.group(1), re.DOTALL), 
       xml, flags=re.DOTALL) 

<trkseg> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
</trkseg> 

이 방법이 있습니다 어떤 문자열 속성에 문자열 "<trkpt"이 포함되어있는 경우 휴식을 취할 수 있지만 실제로 파서는 사용하지 않는 것이 문제입니다.

+0

멋진 조작법이지만 추가 교묘함으로 인해 코드를 읽기가 너무 어렵게 만듭니다. 어쨌든 고마워! – heltonbiker

1

<trkseg>을 보관 하시겠습니까? 그렇다면, 이것은 당신을 위해 일할 수 있습니다 :

print re.sub('([^gt])>\s*<', '\g<1>><', xml, re.DOTALL) 

이전 요소가 t 또는 g로 끝나지 않는 조건에서 요소 사이의 모든 공백을 제거합니다.

<trkseg> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt> 
</trkseg> 
+0

그것은 작동합니다! 어떻게/왜 이것이 효과가 있는지 설명해 주시겠습니까? 여기에 어떤 정규식 개념이 사용됩니까? 명령에서 어디에서 구체적인지 알 수는 없었습니다 ...? – heltonbiker

+1

[^ tg] 비트는 t 또는 g가 아닌 문자와 일치합니다. 괄호 사이에 있으므로 일치하는 문자가 \ <1> 대체 문자열에 추가 될 수 있습니다. – user711413

+1

그래도 여전히 다른 파일에는 트릭을 망칠 수있는'g' 또는't' 태그가있을 수 있습니다 ... : o ( – heltonbiker

0

또 다른 한 줄은

print re.sub("(<trkpt.+?>).*?(<time>.+?</time>).*?(<ele>.+?</ele>).*?(</trkpt>)", 
      r'\1\2\3\4', xml, re.DOTALL) 

이 다른 태그를 쉽게 변경할 수 있다는 장점이있다

<trkseg> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt> 
    <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt> 
</trkseg> 

을 생산하고있다.

+1

불행히도, 나는 의존하고 싶지 않습니다. 내부의 태그의 특정 주문에 ... – heltonbiker