중복 된 줄을 쌍으로 삭제 하시겠습니까? 발생했습니다. 그것은

오늘이 사용 사례가 발생했습니다. 그것은 첫눈에 간단하게 보이지만, 주변에 바이올린을 켜고 sort, uniq, sedawk는 사소하다고 밝혔다.

어떻게 모두 삭제할 수 있습니다 쌍의 중복 라인을? 다시 말해, 주어진 행에 짝수의 복제본이 있으면 모두 삭제하십시오. 홀수의 중복 행이 있으면 하나를 제외하고 모두 삭제하십시오. (정렬 된 입력을 가정 할 수 있습니다.)

깨끗하고 우아한 솔루션이 바람직합니다.

입력 예 :

a
a
a
b
b
c
c
c
c
d
d
d
d
d
e

출력 예 :

a
d
e



답변

sed이 질문을 게시 한 지 얼마되지 않아 답을 찾았습니다 . sed지금까지 아무도 사용 하지 않았습니다.

sed '$!N;/^\(.*\)\n\1$/d;P;D'

보다 일반적인 문제 (3 개 또는 4 개 또는 5 개 세트에서 행을 삭제하는 것은 어떻습니까)로 약간의 장난은 다음과 같은 확장 가능한 솔루션을 제공했습니다.

sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp

세 줄의 선을 제거하기 위해 확장 :

sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp

또는 쿼드 라인을 제거하려면 :

sed -e ':top' -e '$!{/\n.*\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1\n\1$/d;P;D' temp

sed 복제본을 검사하기 위해 실제 줄 수보다 더 많은 메모리 저장 공간이 필요하지 않은 스트림에서 실제로 작동 할 수있는 기능인 대부분의 다른 옵션에 비해 추가적인 이점이 있습니다.


으로 cuonglm는 의견에서 지적 제대로 멀티 바이트 문자가 포함 된 줄을 제거하는 C 로켈은 피할 실패에 필요한 설정. 따라서 위의 명령은 다음과 같습니다.

LC_ALL=C sed '$!N;/^\(.*\)\n\1$/d;P;D' temp
LC_ALL=C sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp
LC_ALL=C sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp
# Etc.


답변

매우 우아하지는 않지만 내가 생각해 낼 수있는만큼 간단합니다.

uniq -c input | awk '{if ($1 % 2 == 1) { print substr($0, 9) }}'

substr ()은 uniq출력을 잘라냅니다 . 9,999,999 개가 넘는 행이 복제 될 때까지 작동합니다 (이 경우 uniq의 출력이 9자를 넘을 수 있음).


답변

아래이 awk스크립트를 사용해보십시오 :

#!/usr/bin/awk -f
{
  if ((NR!=1) && (previous!=$0) && (count%2==1)) {
    print previous;
    count=0;
  }
  previous=$0;
  count++;
}
END {
  if (count%2==1) {
    print previous;
  }
}

lines.txt파일이 정렬되어 있다고 가정합니다 .

시험:

$ chmod +x script.awk
$ ./script.awk lines.txt
a
d
e


답변

pcregrep주어진 샘플에 대한 :

pcregrep -Mv '(.)\n\1$' file

또는 더 일반적인 방법으로 :

pcregrep -Mv '(^.*)\n\1$' file


답변

입력이 정렬 된 경우 :

perl -0pe  'while(s/^(.*)\n\1\n//m){}'


답변

python예를 들어 python2.7 이상 에서 이것을 좋아 합니다.

from itertools import groupby
with open('input') as f:
    for k, g in groupby(f):
            if len(list(g)) % 2:
                    print(k),


답변

내가 각 레코드의 해시를 사용하여 awk에 대해 선택한 질문을 이해 했으므로이 경우 RS = \ n이라고 가정하지만 다른 종류의 배열을 고려하도록 변경 될 수 있습니다. 매개 변수 또는 작은 대화 상자를 사용하여 홀수 대신 짝수 번 반복하십시오. 모든 줄은 해시로 사용되며 그 수가 증가합니다. 파일 끝에서 배열이 스캔되고 모든 짝수의 레코드를 인쇄합니다. 확인하기 위해 개수를 포함하고 있지만 a [x]를 제거하면 문제를 해결할 수 있습니다.

HTH

카운트 라인 코드

#!/usr/bin/nawk -f
{a[$0]++}
END{for (x in a) if (a[x]%2!=0) print x,a[x] }

샘플 데이터 :

a
One Sunny Day
a
a
b
my best friend
my best friend
b
c
c
c
One Sunny Day
c
d
my best friend
my best friend
d
d
d
One Sunny Day
d
e
x
k
j
my best friend
my best friend

샘플 실행 :

countlines feed.txt
j 1
k 1
x 1
a 3
One Sunny Day 3
d 5
e 1