2014-03-18 2 views
3

텍스트 파일을 조작하기위한 스크립트를 작성하고 있습니다.BASH - 중복 줄이 있는지 확인하십시오 (y/n)

내가하고 싶은 일은 중복 된 항목이 존재하는지 확인하는 것입니다. 그렇다면 중복 항목이 있는지 확인하고 유지하는 경우 사용자에게 유지 또는 삭제할 것인지 묻습니다.

중복 줄이있는 경우 표시하는 방법을 알고 있지만 배우고 싶은 것은 "중복이 있습니까?"라는 질문에 예/아니오 대답을 얻는 것입니다.

uniq은 명령이 문제없이 완료되는 한 중복이 발견되거나없는 경우 0을 반환합니다.

중복 행이 있는지 알려주 시려면 if 문구에 넣을 수있는 명령은 무엇입니까?

내 파일은 매우 단순하며 단일 열의 값입니다.

+0

Vim을 사용하여 텍스트 파일을 수동으로 필터링하는 것에 반대하지 않는다면 http://stackoverflow.com/questions/1268032에서 'HighlightRepeats' 메소드를 사용하는 것이 좋습니다. 종종 중복 된 파일/폴더를 필터링하고 필터링 된 파일에 쉘 명령을 적용하는 데이 파일을 사용합니다. –

+1

@ F.X 답장을 보내 주셔서 감사합니다. 내 스크립트 내에서 몇 줄을 사용하여이 작업을 수행하고 싶습니다. – DMS

답변

3

당신은 부울 || 연산자와 결합 awk을 사용할 수 있습니다 다음 || 후 블록은 단지 그것을 중복을 발견 의미 awk 명령을 반환 한 경우 실행 얻을 것이다

# Ask question if awk found a duplicate 
awk 'a[$0]++{exit 1}' test.txt || (
    echo -n "remove duplicates? [y/n] " 
    read answer 
    # Remove duplicates if answer was "y" . I'm using `[` the shorthand 
    # of the test command. Check `help [` 
    [ "$answer" == "y" ] && uniq test.txt > test.uniq.txt 
) 

. [] 다른 프로그래밍 언어와 같은 하지 단지 괄호이다 그러나

그러나 기본적인 이해를 위해 나는 또한 if 블록

awk 'a[$0]++{exit 1}' test.txt 

# $? contains the return value of the last command 
if [ $? != 0 ] ; then 
    echo -n "remove duplicates? [y/n] " 
    read answer 
    # check answer 
    if [ "$answer" == "y" ] ; then 
     uniq test.txt > test.uniq.txt    
    fi 
fi 

를 사용하는 예를 보여 드리겠습니다. [test bash builtin 명령과 동의어이며 ]은 마지막 인수입니다. 당신은 이해하기 위해 help [을 읽을 필요가

+0

도움 주셔서 감사합니다. 나는 당신의 코드를 시도 할 것이다. – DMS

1

이 AWK 한 줄을 사용하여 uniq=yes/no을 수행 할 수 있습니다

awk '!seen[$0]{seen[$0]++; i++} END{print (NR>i)?"no":"yes"}' file 
  • AWK는 seen라는 순 배열을 사용합니다.
  • 요소를 고유하게 지정할 때마다 카운터를 늘립니다. i++.
  • 마지막 END 블록에서 우리는이 코드의 레코드 독특한 #으로 기록 # 비교 : (NR>i)?
  • 조건이 중복 레코드은 우리가 no가 그렇지 않으면 yes를 인쇄하는 인쇄 의미 사실이라면.
+0

답장을 보내 주셔서 감사합니다. 선이 어떻게 작동하는지 설명해 주시겠습니까? – DMS

+0

예 확실한 설명 추가. – anubhava

1

빠른 bash는 솔루션 :

#!/bin/bash 

INPUT_FILE=words 

declare -A a 
while read line ; do 
    [ "${a[$line]}" = 'nonempty' ] && duplicates=yes && break 
    a[$line]=nonempty 
done < $INPUT_FILE 

[ "$duplicates" = yes ] && echo -n "Keep duplicates? [Y/n]" && read keepDuplicates 

removeDuplicates() { 
    sort -u $INPUT_FILE > $INPUT_FILE.tmp 
    mv $INPUT_FILE.tmp $INPUT_FILE 
} 

[ "$keepDuplicates" != "Y" ] && removeDuplicates 

스크립트는 INPUT_FILE 및 저장 키와 연관 배열 a의 각 라인에서 라인으로 라인을 읽고 문자열을 설정합니다 값으로 nonempty. 값을 저장하기 전에 먼저 이미 있는지 여부를 확인합니다. 복제본이 발견되면 duplicates 플래그를 설정 한 다음주기를 벗어납니다.

나중에 플래그가 설정되어 있는지 확인하고 사용자에게 복제본을 보관할지 여부를 묻습니다. 그들이 Y 이외의 다른 답을하면 removeDuplicates 함수를 호출하여 sort -u을 사용하여 중복을 제거합니다. ${a[$line]}은 키 $line에 대해 연관 배열 a의 값으로 계산됩니다. [ "$duplicates" = yes ]은 테스트를위한 bash 내장 구문입니다. 테스트가 성공하면 && 다음에 오는 것이 평가됩니다.

그러나 awk 솔루션은 더 빠를 가능성이 높으므로 더 큰 파일을 처리 할 예정이라면 사용하는 것이 좋습니다.

+0

감사합니다 jkbkot! 이 코드가 어떻게 작동하는지 간단하게 설명해 주시겠습니까? 나는 신인이다. – DMS

+0

@DMS 아무런 문제가 없다. 설명을 추가했다. Btw, upvoting 충분히 감사합니다;) 또한 답변 중 하나를 받아들이는 사이트를 유지하기 위해 노력하십시오. 해피 코딩! –

5

아마 다양한 위해서,이 작업을 수행 할 awk를 사용하지만 것, 여기에 같은 일을 수행하는 간단한 파이프입니다 :

$ { sort | uniq -d | grep . -qc; } < noduplicates.txt; echo $? 
1 
$ { sort | uniq -d | grep . -qc; } < duplicates.txt; echo $? 
0 

sort + uniq -d 만 라인을 중복 있는지 확인을 (이 인접하지 않아도 됨)은 stdout에 인쇄되고 grep . -c은 유용한 부작용이있는 wc -l을 모방하는 행을 계산합니다. 일치하지 않는 경우 (즉, 0 인 경우) 1을 출력하고 -q은 출력을 무시하므로 출력이 무시됩니다. 스크립트에서 자동으로 사용할 수 있도록 줄 수를 인쇄하십시오.

has_duplicates() 
{ 
    { 
    sort | uniq -d | grep . -qc 
    } < "$1" 
} 

if has_duplicates myfile.txt; then 
    echo "myfile.txt has duplicate lines" 
else 
    echo "myfile.txt has no duplicate lines" 
fi 
관련 문제