쉘 스크립트를 사용하여 문자열에서 모든 중복 단어 제거


12

나는 같은 문자열을 가지고있다.

"aaa,aaa,aaa,bbb,bbb,ccc,bbb,ccc"

문자열에서 중복 단어를 제거하고 싶습니다. 출력은 다음과 같습니다.

"aaa,bbb,ccc"

나는이 코드 소스를 시도

$ echo "zebra ant spider spider ant zebra ant" | xargs -n1 | sort -u | xargs

동일한 값으로 올바르게 작동하지만 변수 값을 제공하면 모든 중복 단어도 표시됩니다.

중복 값을 제거하는 방법

최신 정보

내 질문은 사용자가 같은 경우 해당하는 모든 값을 단일 문자열에 추가하는 것입니다.

   user name    | colour
    AAA         | red
    AAA         | black
    BBB         | red
    BBB         | blue
    AAA         | blue
    AAA         | red
    CCC         | red
    CCC         | red
    AAA         | green
    AAA         | red
    AAA         | black
    BBB         | red
    BBB         | blue
    AAA         | blue
    AAA         | red
    CCC         | red
    CCC         | red
    AAA         | green

코딩에서 나는 모든 별개의 사용자를 가져온 다음 색상 문자열을 성공적으로 연결합니다.

while read the records 

    if [ "$c" == "" ]; then  #$c I defined global
        c="$colour1"
    else
        c="$c,$colour1" 
    fi

이 $ c 변수를 인쇄하면 출력을 얻습니다 (사용자 AAA의 경우)

"red,black,blue,red,green,red,black,blue,red,green,"

중복 색상을 제거하고 싶습니다. 원하는 출력은 다음과 같아야합니다.

"red,black,blue,green"

이 원하는 출력을 위해 위의 코드를 사용했습니다.

 echo "zebra ant spider spider ant zebra ant" | xargs -n1 | sort -u | xargs

그러나 중복 값으로 출력을 표시하고 있습니다.

"빨강, 검정, 파랑, 빨강, 녹색, 빨강, 검정, 파랑, 빨강, 녹색"


3
사용중인 문제가 무엇인지 명확히하십시오. "변수 값을 줄 때"라는 말의 의미를 이해하지 못합니다. 어떤 가치를 제공합니까? 어디에서 실패합니까?
terdon

echo 'aaa aaa aaa bbb bbb ccc bbb ccc' | xargs -n1 | sort -u | xargs제공 aaa bbb ccc이 변수의 문자열로 .. 당신이 피곤하고있어 출력 정확한 코드를 보여줄 필요가 그래서 .. :s='aaa aaa aaa bbb bbb ccc bbb ccc'; echo "$s" | xargs -n1 | sort -u | xargs
Sundeep

문자열 값은 동적으로 제공됩니다. 동일한 값을 인쇄하고 있습니다 (중복 값 포함).
Urvashi

1
예, 실패한 코드를 보여주십시오. 그렇지 않으면 무엇이 잘못되었을 수 있는지 어떻게 알 수 있습니까?
Sundeep

주문이 중요합니까?
Jacob Vlijm

답변:


12

재미로 한 번 더 awk

$ a="aaa bbb aaa bbb ccc aaa ddd bbb ccc"
$ echo "$a" | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}'
aaa bbb ccc ddd 

그건 그렇고, 당신의 솔루션조차 변수와 함께 잘 작동합니다 :

$ b="zebra ant spider spider ant zebra ant" 
$ echo "$b" | xargs -n1 | sort -u | xargs
ant spider zebra

깔끔한 접근. 내가해야 할 유일한 조정은 %s대신에 사용 하는 것이 었습니다 %s%s. 그 이유는 내가 결과를 통해 for 루프를 수행했기 때문에 두 개의 공백이 정규식 일치와 관련된 몇 가지 문제를 일으켰 기 때문입니다.
JeremyCanfield

9

tr, sortuniq

echo "zebra ant spider spider ant zebra ant" | tr ' ' '\n' | sort | uniq

또는

echo "zebra ant spider spider ant zebra ant" | tr ' ' '\n' | sort | uniq | xargs 

한 줄을 얻기 위해


| xargs출력을 한 줄에 다시 결합하려면 추가해야 합니다.
Philippos

4
또는을 사용하십시오 sort -u. 또는 awk '!u[$0]++.
Benoît

2
@ Benoît 와우, 나는 몰랐다 sort -u. 나는이 sort | uniq모든 시간을 사용 하고 있습니다. 낭비되는 키 스트로크
Gardenhead

8
$ echo "zebra ant spider spider ant zebra ant"  | awk -v RS="[ \n]+" '!n[$0]++' 
zebra
ant
spider

1
매우 영리한!!!!
George Vasiliou

@GeorgeVasiliou, 감사합니다 [또는 진실을 말하면 매우 게으
릅니다

2

gnu로 sed:

sed ':s;s/\(\<\S*\>\)\(.*\)\<\1\>/\1\2/g;ts'

;s/ */ /g중복 된 공백을 제거하기 위해 추가 할 수 있습니다 .

다음과 같은 기능 :이 줄에서 단어가 두 번째이면 더 이상 중복이 발견되지 않을 때까지 단어를 제거하고 다시 시작하십시오.


무엇 \<\>?
someonewithpc

@someonewithpc 문자가 일치하지 않지만 하위 문자열이 일치하지 않도록 단어의 시작과 끝이 일치합니다.
Philippos

멋지지만 휴대용인가요? 또한 단어가 공백으로 분리되지 않습니까? 공백이 아닌 단어 끝과 일치하도록 중복으로 보입니다.
someonewithpc

1
@someonewithpc 아니요, 표준이 아니기 때문에 gnu sed을 작성했습니다 . 좋은 부분은 첫 번째 문자열과 마지막 문자열을 따로 처리 할 필요가 없다는 것입니다.
Philippos

2
perl -lane '$,=$";print grep { ! $h{$_}++ } @F'

2

필수 awk 솔루션 :

$ echo "ant zebra ant spider spider ant zebra ant" | 
   awk -vRS=" " -vORS=" " '!a[$1] {a[$1]++} END{ for (x in a) print x;  } ' ; echo
zebra ant spider 

(마지막 echo줄 바꿈이 있습니다)


awk 하나 더하기! 나는 단지 재미를 위해 awk 솔루션을 만들고있었습니다. 배열 키에서 awk가 무작위로 발생하기 때문에 END 섹션에서 임의의 순서로 단어가 인쇄 될 가능성이 있습니다.
George Vasiliou

예, 본질적으로 임의의 순서로 인쇄됩니다. 그러나 sort솔루션은 원래 순서를 유지하지 않습니다.
ilkkachu

예, 좋은 지적입니다! 입력과 다른 순서로 인쇄를 정렬 할 수도 있습니다.
George Vasiliou

1
@ilkkachu 사실 우리는 입력이 끝날 때까지 기다릴 필요가 없습니다. 코드를 약간 수정하여 인쇄 여부를 결정할 수 있습니다. awk -vRS=" " -vORS=" " '!a[$1]++ {print $1}' ; echo이렇게하면 주문이 유지됩니다.

1

파이썬

옵션 1

#!/usr/bin/env python
# get_unique_words.py

import sys

l = []
for w in sys.argv[1].split(','):
  if w not in l:
    l += [ w ]
print ','.join(l)

실행 가능하게 만든 다음 Bash에서 호출하십시오.

$ ./get_unique_words.py "aaa,aaa,aaa,bbb,bbb,ccc,bbb,ccc"
aaa,bbb,ccc

또는 Bash 함수로 구현할 수 있지만 구문이 지저분합니다.

get_unique_words(){
  python -c "
l = []
for w in '$1'.split(','):
  if w not in l:
    l += [ w ]
print ','.join(l)"
}

옵션 2

이 옵션은 필요한 경우 단일 라이너가 될 수 있습니다.

#!/usr/bin/env python
# get_unique_words.py

import sys

s_in = sys.argv[1]
l_in = s_in.split(',') # Turn string into a list.
set_out = set(l_in) # Turning a list into a set removes duplicates items.
s_out = ','.join(set_out) 
print s_out

배쉬에서 :

get_unique_words(){
  python -c "print ','.join(set('$1'.split(',')))"
}

0
cat filename | awk '{ delete a; for (i=1; i<=NF; i++) a[$i]++; n=asorti(a, b); for (i=1; i<=n; i++) printf b[i]" "; print "" }' > newfile

나는 그것을 얻지 못한다
Pierre.Vriens

1
코드에 대한 설명이 부족합니다. 아무런 설명도없이 일어나고있는 일을 따르는 것은 어렵습니다. 또한 잘못된 것으로 보이는 데이터 (공백으로 구분 된 필드)와 awk사용중인 특정 구현에 대한 가정을하는 것 같습니다 ( asorti()표준 awk기능이 아님).
Kusalananda

0

파일에서 원래 테이블 형식 데이터 사용 file:

sed '1d' file | sort -u |
awk '{ color[$1] = ( color[$1] == "" ? $3 : color[$1] "," $3 ) }
     END { for (user in color) print user, color[user] }'

이것은 생성

CCC red
BBB blue,red
AAA black,blue,green,red

파이프 라인의 3 단계 :

  1. sed명령은 읽고 싶지 않은 헤더 인 첫 번째 줄을 제거합니다.
  2. sort명령은 우리에게 독특한 라인을 제공합니다. 다음의 샘플 데이터는 sort다음과 같습니다.

    AAA         | black
    AAA         | blue
    AAA         | green
    AAA         | red
    BBB         | blue
    BBB         | red
    CCC         | red
  3. awk명령이 데이터를 받아 배열의 각 사용자에 대한 콤마로 구분 된 문자열을 생성한다 color(사용자 이름이 배열에 열쇠). 마지막에 ( END블록에서) 수집 된 모든 데이터가 출력됩니다.

-2
a="aaa aaa aaa bbb bbb ccc bbb ccc"
for item in $a
do
   echo $item
done | sort -u | (while read i; do ans="$ans $i"; done ; echo $ans)

코드 작동 방식과 왜 그렇게했는지에 대한 설명을 추가하십시오.
xhienne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.