2009-12-09 21 views
7

Aşağıdaki boşlukla ayrılmış girdileri içeren bir değişkeni var.Bir değişkendeki yinelenenleri sıralamadan çıkarma

variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 

Yinelenenleri ayırmadan nasıl silebilirim?

#Something like this. 
new_variable="apple lemon papaya avocado grapes mango banana" 

Buralarda bir değişkenin çiftleri kaldırarak başarmak bir senaryo bulundu, ancak sıralama içeriğini yapar gelmiş. nasıl çalıştığını

#Not something like this. 
new_variable=$(echo "$variable"|tr " " "\n"|sort|uniq|tr "\n" " ") 
echo $new_variable 
apple avocado banana grapes lemon mango papaya 

cevap

19
new_variable=$(awk 'BEGIN{RS=ORS=" "}!a[$0]++' <<<$variable); 

aşağıda açıklanmıştır: Bir kaydın yerine bir alan olarak $ değişkeni her meyveyi davranır böylece

RS (Giriş Kayıt Ayırıcı) bir boşluk ayarlanır. Sınıflandırılmamış benzersiz sihir, a! $ [$ 0] ++ ile gerçekleşir. Awk ilişkilendirici dizileri desteklediğinden, geçerli kaydı ($ 0) diziye a [] olarak anahtar olarak kullanır. Bu anahtar daha önce görülmemişse, [0 $] '0' olarak değerlendirilir (unset indeksleri için awk'nin varsayılan değeri) ve daha sonra TRUE değerini döndürmesi reddedilir. Daha sonra, bir ifadenin TRUE değerini döndürmesi ve '{commands}' verilmemesi durumunda awk'nin '$ 0' basmaya varsayılan olacağı gerçeğinden yararlanıyorum. Son olarak, bu anahtarın artık TRUE değerini döndüremeyeceği ve böylece tekrarlanan değerlerin hiçbir zaman basılmadığı şekilde bir [$ 0] artırılır. ORS (Çıkış Kaydı Ayırıcı) giriş formatını taklit etmek için bir boşluğa ayarlanır. Aynı çıktıyı üretir bu komutun

Daha az veciz versiyonu olacağını şu:

awk 'BEGIN{RS=ORS=" "}{ if (a[$0] == 0){ a[$0] += 1; print $0}}' 

Gotta

DÜZENLEME

Bunu yapmak gerekirse awk =) aşk saf Bash 2'de.çalıştırdığınızda

#!/bin/bash  

variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 
temp="$variable" 

new_variable="${temp%% *}" 

while [[ "$temp" != ${new_variable##* } ]]; do 
    temp=${temp//${temp%% *} /} 
    new_variable="$new_variable ${temp%% *}" 
done 

echo $new_variable; 
+0

bazı açıklamalar eklemek için bu düzenlerseniz sana +1 – Nifle

+0

vereceğiz Söz verildiği gibi +1. – Nifle

+0

Tatlı :) Açıklama için teşekkürler. – jhwist

1

kabuk

declare -a arr 
variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 
set -- $variable 
count=0 
for c in [email protected] 
do 
    flag=0 
    for((i=0;i<=${#arr[@]}-1;i++)) 
    do 
     if [ "${arr[$i]}" == "$c" ] ;then 
      flag=1 
      break 
     fi 
    done 
    if [ "$flag" -eq 0 ] ; then 
     arr[$count]="$c" 
     count=$((count+1)) 
    fi 
done 
for((i=0;i<=${#arr[@]}-1;i++)) 
do 
    echo "result: ${arr[$i]}" 
done 

Sonucu:

linux# ./myscript.sh 
result: apple 
result: lemon 
result: papaya 
result: avocado 
result: grapes 
result: mango 
result: banana 

VEYA kullanmak istiyorsanız

awk 'BEGIN{RS=ORS=" "} (!($0 in a)){a[$0];print}' 
4

Bu boru hattı aval 1+, bu öneririm Sürüm orijinal sipariş koruyarak çalışır:

variable=$(echo "$variable" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-) 
3

Saf Bash:

variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 

declare new_value='' 

for item in $variable; do 
    if [[ ! $new_value =~ $item ]] ; then # first time? 
    new_value="$new_value $item" 
    fi 
done 
new_value=${new_value:1}     # remove leading blank 
+0

İyi bir çözüm, ancak bunun '= ~' operatöründen dolayı Bash 3.X'e kilitlendiğini unutmayın. – SiegeX

+0

Pekala. Neden bir şeyi değiştirmeliyim? Bu senin hatandı. –

1

Z Kabuk: Saf olarak

% variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 
% print ${(zu)variable}                
apple lemon papaya avocado grapes mango banana 
3

taşınabilir sh:

 
words="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 
seen= 
for word in $words; do 
    case $seen in 
    $word\ * | *\ $word | *\ $word\ * | $word) 
     # already seen 
     ;; 
    *) 
     seen="$seen $word" 
     ;; 
    esac 
done 
echo $seen 
0

başka awk çözeltisi:

#!/bin/bash 
variable="apple lemon papaya avocado lemon grapes papaya apple avocado mango banana" 
variable=$(printf '%s\n' "$variable" | awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}') 
variable="${variable%,*}" 
echo "$variable" 

Çıkış:

apple lemon papaya avocado grapes mango banana 
0

Perl çözeltisi:

perl -le 'for (@ARGV){ $h{$_}++ }; for (keys %h){ print $_ }' $variable

@ARGV döngü ile h karma doldurma, listeyi $variable
döngü gelen giriş parametreleri listesi $_
değişken 0 h karma tuşlarıyladöngü ve baskı her biri

grapes 
avocado 
apple 
lemon 
banana 
mango 
papaya 

Bu varyasyon çıkış alfabetik sonra $a cmp $b

perl -le 'for (@ARGV){ $h{$_}++ }; for (sort { $h{$a} <=> $h{$b} || $a cmp $b } keys %h){ print "$h{$_}\t$_" }' $variable

1  banana 
1  grapes 
1  mango 
2  apple 
2  avocado 
2  lemon 
2  papaya 
frekans $h{$a} <=> $h{$b} ilk kriteri ve basar

Bu varyasyon, sonuncu ile aynı çıktıyı üretir.
Ancak bunun yerine bir giriş kabuk değişkeninin her satırda bir meyve ile, bir giriş dosyası 'meyveler' kullanır:

perl -lne '$h{$_}++; END{ for (sort { $h{$a} <=> $h{$b} || $a cmp $b } keys %h){ print "$h{$_}\t$_" } }' fruits