파일에서 중복 행을 삭제하지 않고 식별합니까?


11

긴 항목 목록이있는 텍스트 파일로 참조가 있고 각각 두 개 이상의 필드가 있습니다.

첫 번째 열은 참조의 URL입니다. 두 번째 열은 제목이며 입력 방법에 따라 약간 다를 수 있습니다. 존재하거나 존재하지 않을 수있는 제 3 필드에 대해서도 동일하다.

첫 번째 필드 (참조 URL)가 동일한 항목을 식별하지만 제거하지는 않습니다. 나는 알고 sort -k1,1 -u있지만 첫 번째 적중을 제외한 모든 것을 자동으로 (대화식으로) 제거합니다. 유지할 것을 선택할 수 있도록 알려주는 방법이 있습니까?

첫 번째 필드 ( http://unix.stackexchange.com/questions/49569/) 가 동일한 세 줄의 아래 추출에서 추가 태그 (정렬, CLI)가 있고 줄 1과 3을 삭제하기 때문에 줄 2를 유지하고 싶습니다.

http://unix.stackexchange.com/questions/49569/  unique-lines-based-on-the-first-field
http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field   sort, CLI
http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field

이러한 "중복"을 식별하는 데 도움이되는 프로그램이 있습니까? 그런 다음 줄 1과 3을 개인적으로 삭제하여 수동으로 정리할 수 있습니까?


나는 당신의 예를 이해하지 못합니다 ... 입력과 예상 출력의보다 단순화 된 버전을 줄 수 있습니까?
Oli

지금 더 명확한 지 확인하십시오.
DK Bose

답변:


9

귀하의 질문을 이해하면 다음과 같은 것이 필요하다고 생각합니다.

for dup in $(sort -k1,1 -u file.txt | cut -d' ' -f1); do grep -n -- "$dup" file.txt; done

또는:

for dup in $(cut -d " " -f1 file.txt | uniq -d); do grep -n -- "$dup" file.txt; done

file.txt관심있는 데이터가 들어있는 파일은 어디에 있습니까 ?

출력에서 첫 번째 필드가 두 번 이상 발견되는 라인과 라인의 수를 볼 수 있습니다.


3
감사합니다 : 심지어 cut -d " " -f1 file.txt | uniq -d나에게 좋은 결과를줍니다.
DK Bose

@DKBose 아마도 더 많은 가능성이 있지만 사용하고 싶었던 명령도 있습니다.
Radu Rădeanu

감사. 두 번째 명령은 내가 좋아하는 명령입니다. 첫 번째를 제거 할 수 있습니다. 그리고 당신도 좋은 코드를 설명한다면 :)
DK Bose

10

이것은 uniq명령 으로 해결할 수있는 고전적인 문제입니다 . uniq중복 된 연속 줄을 감지하고 중복을 제거 하거나 ( -u, --unique) 중복 만 유지할 수 있습니다 ( -d, --repeated).

중복 행의 순서는 중요하지 않으므로 먼저 정렬해야합니다. 그런 다음 uniq고유 한 줄만 인쇄 하는 데 사용하십시오 .

sort yourfile.txt | uniq -u

옵션의 중복 수를 인쇄 하는 -c( --count) 옵션 도 -d있습니다. 자세한 내용은 매뉴얼 페이지 uniq를 참조하십시오.


첫 번째 필드 다음 부분을 실제로 신경 쓰지 않으면 다음 명령을 사용하여 중복 키를 찾아 각 행 번호를 인쇄하십시오 ( | sort -n출력을 행별로 정렬하도록 다른 행 을 추가하십시오 ).

 cut -d ' ' -f1 .bash_history | nl | sort -k2 | uniq -s8 -D

첫 번째 필드를 키로 사용하여 중복 행을 보려면 직접을 사용할 수 없습니다 uniq. 자동화를 어렵게 만드는 문제는 제목 부분이 다양하지만 프로그램이 마지막 제목으로 간주 할 제목을 자동으로 결정할 수 없다는 것입니다.

다음은 script.awk텍스트 파일을 입력으로 사용하고 모든 중복 행을 인쇄하여 삭제할 파일을 결정할 수 있는 AWK 스크립트 (에 저장 )입니다. ( awk -f script.awk yourfile.txt)

#!/usr/bin/awk -f
{
    # Store the line ($0) grouped per URL ($1) with line number (NR) as key
    lines[$1][NR] = $0;
}
END {
    for (url in lines) {
        # find lines that have the URL occur multiple times
        if (length(lines[url]) > 1) {
            for (lineno in lines[url]) {
                # Print duplicate line for decision purposes
                print lines[url][lineno];
                # Alternative: print line number and line
                #print lineno, lines[url][lineno];
            }
        }
    }
}

나는 이것이 내가 원하는 것에 가깝다고 생각하지만`-f, --skip-fields = N의 반대가 필요하다 (첫 번째 N 필드를 비교하지 마십시오). 다시 말해, 첫 번째 필드 인 URL 만 고려하고 싶습니다.
DK Bose

@DKBose 고정 된 수의 문자로 제한 하는 -w( --check-chars) 옵션이 있지만 예제를 보면 첫 번째 필드가 가변적입니다. 때문에 uniq필드 선택을 지원하지 않습니다, 당신은 해결 방법을 사용해야합니다. 더 쉬운 AWK 예제를 포함하겠습니다.
Lekensteyn

예, 방금보고 -w있었지만 첫 번째 필드의 길이는 가변적입니다. (
DK Bose

@DKBose 최신 편집을 참조하십시오
Lekensteyn

1
awk : script.awk : line 4 : 구문 오류 또는 근처에 있음 [awk : script.awk : line 10 : 구문 오류 또는 근처에 있음 [awk : script.awk : line 18 : 구문 오류가 있음}
DK Bose

2

이 글을 올바르게 읽으면

awk '{print $1}' file | sort | uniq -c | 
    while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done

그러면 줄이 포함 된 줄 번호와 줄 자체가 인쇄됩니다. 예를 들어이 파일을 사용하면

foo bar baz
http://unix.stackexchange.com/questions/49569/  unique-lines-based-on-the-first-field
bar foo baz
http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field   sort, CLI
baz foo bar
http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field

이 출력을 생성합니다 :

2:http://unix.stackexchange.com/questions/49569/  unique-lines-based-on-the-first-field
4:http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field   sort, CLI
6:http://unix.stackexchange.com/questions/49569/  Unique lines based on the first field

줄 번호 만 인쇄하려면 할 수 있습니다

awk '{print $1}' file | sort | uniq -c | 
 while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done | cut -d: -f 1

그리고 라인 만 인쇄하려면 :

awk '{print $1}' file | sort | uniq -c | 
while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done | cut -d: -f 2-

설명:

awk스크립트는 단지 1 공간이 파일의 필드를 구분 인쇄합니다. $NN 번째 필드를 인쇄하는 데 사용 합니다. sort그것을 정렬하고 uniq -c각 줄의 발생 횟수를 계산합니다.

이 다음에 전달되는 while등의 발생 횟수 저장 루프 $num와 같은 라인을 $dupe하고있는 경우는 $num그것을 사용, 그 라인에 대한 파일을 검색합니다 (이 한 번 이상에 중복 그래서)보다 큰 하나입니다 -n줄 번호를 인쇄 할 수 있습니다. 는 --말한다 grep무엇을 다음하는 경우에 유용한 명령 행 옵션이 아니라는 것을 $dupe시작할 수 있습니다 -.


1

의심 할 여지없이 목록에서 가장 장황한 것이 아마 더 짧을 수 있습니다.

#!/usr/bin/python3
import collections
file = "file.txt"

def find_duplicates(file):
    with open(file, "r") as sourcefile:
        data = sourcefile.readlines()
    splitlines = [
        (index, data[index].split("  ")) for index in range(0, len(data))
        ]
    lineheaders = [item[1][0] for item in splitlines]
    dups = [x for x, y in collections.Counter(lineheaders).items() if y > 1]
    dupsdata = []
    for item in dups:
        occurrences = [
            splitlines_item[0] for splitlines_item in splitlines\
                       if splitlines_item[1][0] == item
            ]
        corresponding_lines = [
            "["+str(index)+"] "+data[index] for index in occurrences
            ]
        dupsdata.append((occurrences, corresponding_lines))

    # printing output   
    print("found duplicates:\n"+"-"*17)
    for index in range(0, len(dups)):
        print(dups[index], dupsdata[index][0])
        lines = [item for item in dupsdata[index][1]]
        for line in lines:
            print(line, end = "")


find_duplicates(file)

다음과 같은 텍스트 파일을 제공합니다.

monkey  banana
dog  bone
monkey  banana peanut
cat  mice
dog  cowmeat

다음과 같은 출력 :

found duplicates:
-----------------
dog [1, 4]
[1] dog  bone
[4] dog  cowmeat
monkey [0, 2]
[0] monkey  banana
[2] monkey  banana peanut

제거 할 줄을 고르면 :

removelist = [2,1]

def remove_duplicates(file, removelist):
    removelist = sorted(removelist, reverse=True)
    with open(file, "r") as sourcefile:
        data = sourcefile.readlines()
    for index in removelist:
        data.pop(index)
    with open(file, "wt") as sourcefile:
        for line in data:
            sourcefile.write(line)

remove_duplicates(file, removelist)

0

정렬 된 다음을 참조하십시오 file.txt.

addons.mozilla.org/en-US/firefox/addon/click-to-play-per-element/ ::: C2P per-element
addons.mozilla.org/en-us/firefox/addon/prospector-oneLiner/ ::: OneLiner
askubuntu.com/q/21033 ::: What is the difference between gksudo and gksu?
askubuntu.com/q/21148 ::: openoffice calc sheet tabs (also askubuntu.com/q/138623)
askubuntu.com/q/50540 ::: What is Ubuntu's Definition of a "Registered Application"?
askubuntu.com/q/53762 ::: How to use lm-sensors?
askubuntu.com/q/53762 ::: how-to-use-to-use-lm-sensors
stackoverflow.com/q/4594319 ::: bash - shell replace cr\lf by comma
stackoverflow.com/q/4594319 ::: shell replace cr\lf by comma
wiki.ubuntu.com/ClipboardPersistence ::: ClipboardPersistence
wiki.ubuntu.com/ClipboardPersistence ::: ClipboardPersistence - Ubuntu Wiki
www.youtube.com/watch?v=1olY5Qzmbk8 ::: Create new mime types in Ubuntu
www.youtube.com/watch?v=2hu9JrdSXB8 ::: Change mouse cursor
www.youtube.com/watch?v=Yxfa2fXJ1Wc ::: Mouse cursor size

목록이 짧기 때문에 (정렬 후) 세 세트의 중복이 있음을 알 수 있습니다.

그런 다음 예를 들어 다음과 같이 유지할 수 있습니다.

askubuntu.com/q/53762 ::: How to use lm-sensors?

오히려

askubuntu.com/q/53762 ::: how-to-use-to-use-lm-sensors

그러나 더 긴 목록을 보려면 이것이 어려울 것입니다. 하나는 제안 uniq하고 다른 하나는 제안하는 두 가지 답변을 바탕 cut으로이 명령이 원하는 출력을 제공한다는 것을 알았습니다.

$ cut -d " " -f1 file.txt | uniq -d
askubuntu.com/q/53762
stackoverflow.com/q/4594319
wiki.ubuntu.com/ClipboardPersistence
$

의 다른 변형으로 답변을 업데이트했습니다 cut. 중복 제거 작업을 수행하는 경우 줄 번호가 매우 유용 할 수 있습니다. 모든 복사본을 인쇄하려면 -D대신 옵션을 사용하십시오 -d.
Lekensteyn

for dup in $(cut -d " " -f1 file.txt | uniq -d); do grep -n $dup file.txt; done내 대답에서와 같이 더 잘 사용한다고 생각합니다 . 관심있는 항목에 대한 더 나은 미리보기를 제공합니다.
Radu Rădeanu

0

그녀는 내가 그것을 해결 한 방법입니다 :

file_with_duplicates :

1,a,c
2,a,d
3,a,e <--duplicate
4,a,t
5,b,k <--duplicate
6,b,l
7,b,s
8,b,j
1,b,l
3,a,d <--duplicate
5,b,l <--duplicate

1 열과 2 열을 기준으로 정렬 및 중복 제거 된 파일

sort -t',' -k1,1 -k2,2 -u file_with_duplicates

열 1과 열 2로만 정렬 된 파일

sort -t',' -k1,1 -k2,2 file_with_duplicates

차이점 만 표시하십시오.

diff <(sort -t',' -k1,1 -k2,2 -u file_with_duplicates) <(sort -t',' -k1,1 -k2,2 file_with_duplicates)

 3a4
   3,a,d
 6a8
   5,b,l
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.