줄에 서로 다른 문자가 2개 이상 있는지 확인하세요.

줄에 서로 다른 문자가 2개 이상 있는지 확인하세요.

각 줄에 한 단어가 포함된 텍스트 파일이 있습니다. 두 개 이상의 문자가 포함되지 않은 줄을 삭제하려고 합니다. 예를 들어 파일은 다음과 같습니다.

words
books
aaa
letters 
zzzz

출력 파일이 다음과 같기를 원합니다.

words
books
letters

uniq -cthen을 사용하여 단어를 그룹화하는 대신 각 단어를 개별 문자로 분리하려고 시도했지만 wc -lif 문에 갇혔습니다. 또한 이 작업을 수행하는 더 쉬운 방법이 있어야 한다고 생각합니다. 이 문제를 해결할 수 있는 다른 방법은 생각할 수 없습니다.

답변1

당신이 의미한다고 가정특징문자 대신 (예: 또는 문자가 아니더라도 또는 ...을 포함하는 줄을 제거하려는 경우 ):11.1

grep -vx -e '' -e '\(.\)\1*'

또는:

grep -vx '\(\(.\)\2*\)\{0,1\}'

즉, -v한 문자( )로 .시작 하고 그 뒤에 동일한 문자( \1캡처된 콘텐츠에 대한 역참조 )가 이어지는 빈 줄( )을 제거( )합니다 . 줄이 끝날 때까지 \(...\)0회 이상( ) 반복됩니다 ( 패턴을 시작 부분에 고정). 줄과 끝).*-x

표준 ERE에는 역참조가 없기 때문에(BRE에만 있음) 여기서는 egrep또는 를 사용할 수 없습니다 .grep -E

두 개 이상의 서로 다른 문자가 포함된 줄의 경우 다른 유형의 문자는 무시됩니다( [[:alpha:]]여기에서는편지, 즉 고려되는 모든 문자알파벳순으로귀하의 지역에서):

grep -vx '[^[:alpha:]]*
[^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\1\)*[^[:alpha:]]*'

(두 줄에서 이는 두 가지 다른 모드를 전달하는 또 다른 방법입니다.) 또는:

grep -vx '[^[:alpha:]]*\([^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\2\)*[^[:alpha:]]*\)\{0,1\}'

그러면 12345aaa(한 글자만) 또는 (문자 없음)과 같은 -+-+-+-줄이 제거됩니다.

줄 도 제거하려면 Aaaa(예: 문자를 비교할 때 대/소문자 무시) 이 -i옵션을 추가하세요.

문자 수준에서 작동하므로 여러 문자로 표현되는 문자소가 있는 경우 예상한 대로 작동하지 않을 수 있습니다. 예를 들어 다음 출력과 유사한 줄을 제거합니다.

 $ printf 'e\u0300e\u0301\n'
 èé

(GNU printf또는 호환 가능하다고 가정) 그러나 다음과 같지는 않습니다.

 $ printf '\ue8\ue9\n'
 èé

( e\u300자소의 분해 및 \ue8사전 결합 형태는 어디에 있습니까 è? e(U+0065) 및 è(U+00E8)은알파벳순으로, 그러나 악센트/악센트와 결합된 U+0300 또는 U+0301은 제외).

pcregrep문자소를 사용하려면 또는 GNU grep및 해당 옵션을 사용할 수 있습니다 -P.

첫 번째 경우(적어도 두 개의 서로 다른 문자소 클러스터):

grep -vxP '(?:(\X)\1*)?'

두 번째 경우(적어도 두 가지 다른 경우가 있습니다.편지자소 클러스터):

grep -vxP '(?:(?=\PL)\X)*(?:((?=\pL)\X)(?:(?:(?=\PL)\X)*\1(?!\pM))*(?:(?=\PL)\X)*)?'

(?=\PL)\X비알파벳 문자소 클러스터( 비알파벳( ) 및 알파벳 문자소 클러스터 로 시작하는 \X경우 문자소 클러스터( )) 는 어디에 있습니까?(?=...)\PL(?=\pL)\X

\pL성냥편지유니코드를 수정하세요. POSIX 문자 클래스와 달리 [:alpha:]알파벳이 아닌 스크립트의 문자도 포함됩니다.

e\u300\u301, , 가 모두 날카롭고 악센트가 있는 a e\u301\u300인 경우에도 4개의 서로 다른 클러스터로 처리 됩니다 \ue9\u300.\ue8\u301e

또한 한 문자에 여러 문자가 포함된 (U+FB03)과 같은 문자 에 주의하세요.특징.


PCRE를 사용하면 다음을 수행할 수도 있습니다.긍정적인방법:

  • 최소 2개의 다른 문자:

    grep -P '(.).*(?!\1).'
    
  • 최소 2개의 서로 다른 알파벳 문자:

    grep -P '(\pL).*(?!\1)\pL'
    
  • 최소 2개의 서로 다른 문자소 클러스터:

    grep -P '^\X*(\X)\X*(?!\1(?!\pM))\X'
    

    (적어도) 꾸란 한국어의 분해된 형태는 제대로 작동하지 않습니다. PCRE( perlRE 와 반대 \b{g})에는 AFAIK(자소 경계 연산자)가 없으며 유니코드 속성에 대한 지원이 제한되어 있습니다. 우리는 (?!\pM)근사치로 (이 경우 "결합 표시 문자가 따르지 않는 한"을 의미함)를 사용 하지만 이는 여러 부분으로 구성된 한글에서는 작동하지 않습니다.편지/음절그 중에서도 캐릭터부분그런 재산은 없습니다. 려련련예를 들어 삭제합니다. 이제 모든 사람은 다음과 같이 주장할 수도 있습니다.부분독특하다편지...

    perl버전 5.22 이상의 경우 다음과 같이 작성할 수 있습니다.

    perl -Mopen=locale -lne 'print if /\b{g}(\X).*\b{g}(?!\1\b{g})\X/'
    
  • 적어도 2개의 다른편지문자소 클러스터:

    grep -P '^\X*((?=\pL)\X)\X*(?!\1(?!\pM))(?=\pL)\X'
    

    다시 말하지만 에는 적용되지 않습니다 려련련.perl

    perl -Mopen=locale -lne 'print if /\b{g}(?=\pL)(\X).*\b{g}(?!\1\b{g})(?=\pL)\X/'
    

이를 통해 perl다음과 같은 보다 직접적인 접근 방식을 사용할 수 있습니다.

  • 최소 2개의 다른 문자:

    perl -Mopen=locale -MList::MoreUtils=uniq -lne '
      print if uniq(/./g) >= 2'
    
  • 최소 2개의 서로 다른 알파벳 문자:

    perl -Mopen=locale -MList::MoreUtils=uniq -lne '
      print if uniq(/\pL/g) >= 2'
    
  • 최소 2개의 서로 다른 문자소 클러스터:

    perl -Mopen=locale -MList::MoreUtils=uniq -lne '
      print if uniq(/\X/g) >= 2'
    
  • 적어도 2개의 다른편지문자소 클러스터:

    perl -Mopen=locale -MList::MoreUtils=uniq -lne '
      print if uniq(grep /^\pL/, /\X/g) >= 2'
    

답변2

예상되는 결과에 따라 두 단어 이상을 건너뛰고 싶습니다.정확히 똑같다수치:

grep방법:

grep -vE '(.)(\1){2,}' file

산출:

words
books
letters 

파일 수정제자리에다음을 적용할 수 있습니다.sed방법:

sed -Ei '/(.)(\1){2}/d' file

답변3

쿼리에 대한 정방향 검색:

while read -r line; do 
    n=$(echo "$line" | egrep -o . | sort -u);
    [[ ${#n} -gt 1 ]] && echo "$line"; 
done < file

관련 정보