2009-12-13 8 views
2

내가 만든 XML 파일에서 중복 행을 제거하기 위해 VIM을 사용하려고합니다. (ID 번호가 변경됩니다 때문에 파일을 다시 만들 수 없습니다.)Vim에서 중복 줄을 제거 하시겠습니까?

이 파일은 다음과 같이 보입니다 :

<tag k="natural" v="water"/> 
    <tag k="nhd:fcode" v="39004"/> 
    <tag k="natural" v="water"/>

내가 = "자연"V 중복 K 중 하나를 제거하기 위해 노력하고있어를 = "물"줄. \_ 수정자를 사용하여 정규식 바꾸기에 줄 바꿈을 포함 시키려고하면 VIM이 아무것도 찾지 못하는 것 같습니다.

어떤 정규식이나 도구를 사용하면 좋을까요?

답변

0

아무 것도 검색하지 않고 바꾸려고합니까? 대신 g 명령을 시도해 볼 수도 있습니다 : 끝에

:%g/search_expression_here/d 

d가 일치하는 행을 삭제하도록 지시합니다.

here 팁이 더 있습니다. 대신 정력을 사용

+0

감사합니다,하지만 나는 또한 제거 할 수있는 라인을 찾을 수 있도록 위의 세 줄을 일치하는 정규식을 찾기 위해 노력하고있어. – magneticMonster

+0

항상 3 줄입니까? .. 파일의 첫 번째 줄과 마지막 줄이 같은 경우 전체 파일을 반환하는 정규식을 사용하지 않아도됩니다. –

1

당신은

sort filename | uniq -c | grep -v "^[ \t]*1[ \t]" 

같은 것이 중복 라인이 무엇인지 파악하기 위해 수행 한 후 바로 고통 'UNIQ'를 사용하여

+2

고양이가 필요 없습니다. – ghostdog74

+1

grep은 두 번, 20-29, 200-299, ... 번 반복되는 행에서만 작동합니다. 탭이 명령 줄에 나타나야한다는 것을 나타 내기 위해'grep -v '^ [\ t] * 1 [\ t]''를 쓰는 것이 더 나을 것입니다. –

+0

좋은 생각 .. 내가 그걸 덧붙였다 –

1

답변을 방문하고 삭제하는 일반 검색을 사용 'uniq'가 인접한 중복 된 행만 찾거나 데이터 파일이 정렬되어 위치 정보가 손실되는 문제. 어떤 라인이 영원히 반복되지 않을 수있는 경우

, 데이터 소스가 믿을 humungous 한 아니라고 가정하면, 펄 (또는 정규식과 연관 배열을 지원하는 다른 스크립팅 언어)에서 수행하는 비교적 간단

#!/bin/perl -w 
# BEWARE: untested code! 
use strict; 
my(%lines); 
while (<>) 
{ 
    print if !defined $lines{$_}; 
    $lines{$_} = 1; 
} 

그러나 무차별 적으로 사용되는 경우 종료 태그가 합법적으로 반복되므로 XML을 손상시킬 수 있습니다. 이것을 피하는 방법? 'OK to repeat'라인의 화이트리스트에 의해 어쩌면? 물론

#!/bin/perl -w 
# BEWARE: untested code! 
use strict; 
my(%lines); 
while (<>) 
{ 
    if (m%^\s*<[^\s>]+\s[^\s>]+%) 
    { 
     print if !defined $lines{$_}; 
     $lines{$_} = 1; 
    } 
    else 
    { 
     print; 
    } 
} 

은 또한 정규 표현식으로 XML을 처리하는 것은 잘못이라는 (주로 유효) 인수가 : 아니면 값을 공개 태그 만 선은 제거 중복 될 수 있습니다. 이 코딩에서는 XML에 편리한 줄 바꿈이 많이 있다고 가정합니다. 실제 XML에는 일부만 포함되거나 아주 적게 포함될 수 있습니다.

1

주문을 염려하지 않으면 라인을 선택하고 :'<,'>sort u을 할 수 있습니다. 그것은 중복을 분류하고 제거 할 것입니다. 영업에

1

, 당신은 bash는 모든 반복 라인을 제거하는 파이썬 4.0

#!/bin/bash 
# use associative array 
declare -A DUP 
file="myfile.txt" 
while read -r line 
do 
    if [ -z ${DUP[$line]} ];then 
     DUP[$line]=1 
     echo $line >temp 
    fi 
done < "$file" 
mv temp "$file" 
1

있는 경우 :

#!/usr/bin/env python 

import sys 
def remove_identical(filein, fileout) : 
    lines = list() 
    for line in open(filein, 'r').readlines() : 
    if line not in lines : lines.append(line) 
    fout = open(fileout, 'w') 
    fout.write(''.join(lines)) 
    fout.close() 

remove_identical(sys.argv[1], sys.argv[2]) 
1

간단한 정규 표현식이 충분하지됩니다. 내 PatternsOnText plugin

:DeleteDuplicateLinesIgnoring 

명령 (관련 명령은 물론)을 구현했습니다.{pattern}을 제공하여 중복 제거에서 특정 라인을 제외시킬 수도 있습니다.

4

먼저 awk을 사용하면 모든 중복 된 줄을 지우고 순서를 유지할 수 있습니다.

:%!awk '\!_[$0]++' 

제거하고 싶지 않은 다른 중복 줄이 있는지 확실하지 않으면 조건을 추가하십시오.

:%!awk '\!(_[$0]++ && /tag/ && /natural/ && /water/)' 

그러나 XML과 같이 중첩 된 구조를 구문 분석하는 것은 좋지 않은 아이디어입니다. 당신은 항상 망쳐 놓지 않도록 그들을 돌보아야합니다.

:!echo "cat //tag[@k='natural' and @v='water']" | xmllint --shell % 

중복 라인을 단계적으로 삭감 할 수 있습니다 xmllint는 당신에게 파일의 특정 요소의 목록을 제공합니다.

+0

아주 좋아! 너는 Awk보다 더 간결해질 수 없다. – glts

0

bash, python 및 perl 메서드가 작동하지만 이미 vim에있는 것처럼 보입니다. 그런데 왜 같은 기능을 만들 수 없습니다 :이 팁

function! RemoveDuplicateLines() 
    let lines={} 
    let result=[] 
    for lineno in range(line('$')) 
     let line=getline(lineno+1) 
     if (!has_key(lines, line)) 
      let lines[line] = 1 
      let result += [ line ] 
     endif 
    endfor 
    %d 
    call append(0, result) 
    d 
endfunction