シェルスクリプトを使用して文字列からすべての重複する単語を削除する


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 2017年

順序は重要ですか?
Jacob Vlijm 2017年

回答:


12

楽しみのためにもう1つ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ループを実行していて、2つの空白が正規表現の一致でいくつかの課題を引き起こしたためです。
JeremyCanfield

9

そしてtrsortuniq

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 

1行取得する


| xargs出力をもう一度1行に結合するには、追加する必要があります
Philippos

4
またはを使用しますsort -u。またはawk '!u[$0]++
ブノワ・

2
@Benoîtうわー、私は知りませんでしたsort -u。これまでずっと使ってきましsort | uniqた。無駄なキーストローク...
gardenhead 2017年

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

1
非常に賢い!!!!
George Vasiliou 2017年

@GeorgeVasiliou、ありがとう[または実を言うと、非常に怠惰:-)]
JJoao

2

gnuでsed

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

追加;s/ */ /gして重複スペースを削除できます。

このような機能:単語がこの行で2回目にある場合は、それを削除し、重複がなくなるまでやり直します。


何である\<\>
someonewithpc 2017年

@someonewithpc一致する文字はありませんが、部分文字列が一致しないようにするために単語の最初と最後が一致します。
フィリポス

いいですが、移植可能ですか?また、単語は空白で区切られていませんか?空白ではなく単語の終わりに一致しないように冗長に思われる
someonewithpc 2017年

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にプラス1つ!私は楽しみのためだけにawkソリューションも構築していました。配列キーでawkがランダムに発生するため、ENDセクションにランダムな順序で単語が出力される可能性があります。
George Vasiliou 2017年

はい、基本的にランダムな順序で印刷されます。sortただし、このソリューションでは元の順序も保持されません。
ilkkachu 2017年

はい、良い点です!入力とは異なる順序でプリントをソートすることもできます。
George Vasiliou 2017年

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


1
コードに説明がありません。説明がなければ、何が起こっているのかを追跡することは困難です。また、間違っていると思われるデータ(空白で区切られたフィールド)およびawk使用されている特定の実装(asorti()標準awk関数ではありません)についても想定しているようです。
クサラナンダ

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 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.