2014-01-24 74 views
2

我有一個列表的形式大致如下:唯一的標識符替換列表中的重複元素

1 . Fred 1 6 78 8 09 
1 1 Geni 1 4 68 9 34 
2 . Sam 3 4 56 6 89 
3 . Flit 2 4 56 8 34 
3 4 Dog 2 5 67 8 78 
3 . Pig 2 5 67 2 21 

(除了真正的名單爲40萬線長)。

還有反覆在第二列元素(即「‘)

我想用獨特的identifers(如’.1" ,」 0.2" 來代替這些,。」 3" ... 「ñ」)

我試圖用一個bash循環/ sed的組合,要做到這一點,但它沒有工作...

失敗的嘗試:

for i in 1..4 
    do 
    sed -i "s_//._//."$i"_"$i"" 
    done 

(愛喜從本質上講,我試圖讓sed把「。」和「。」替換成每個n。 。ñ」,但這並沒有工作)

回答

5

這裏是一種與awk做到這一點(假設你的文件被稱爲input

$ awk '$2=="."{$2="."++counter}{print}' input 
1 .1 Fred 1 6 78 8 09 
1 1 Geni 1 4 68 9 34 
2 .2 Sam 3 4 56 6 89 
3 .3 Flit 2 4 56 8 34 
3 4 Dog 2 5 67 8 78 
3 .4 Pig 2 5 67 2 21 

awk程序取代第二列($2)如果第二列恰好爲.,則通過連接.與預先計數的計數器(++counter)形成的字符串,然後打印出所有列($2修改與否)({print})。

平原bash的選擇:

c=1 
while read -r a b line ; do 
    if [ "$b" == "." ] ; then 
    echo "$a ."$((c++))" $line" 
    else 
    echo "$a $b $line" 
    fi 
done < input 
+0

我不知道如何使用'sed的做到這一點'。一些答案[這裏](http://stackoverflow.com/questions/12496717/sed-replace-pattern-with-line-number)雖然可能有幫助。 – Mat

+0

+1,用於漂亮簡單的awk。 – anubhava

0

你可以使用這個命令:

awk '{gsub(/\./,c++);print}' filename 

輸出:

1 0 Fred 1 6 78 8 09 
1 1 Geni 1 4 68 9 34 
2 2 Sam 3 4 56 6 89 
3 3 Flit 2 4 56 8 34 
3 4 Dog 2 5 67 8 78 
3 5 Pig 2 5 67 2 21 
1

由於您的問題被標記sedbash,這裏有幾個例子爲了完整性。

只有

使用parameter expansion猛砸。第二列將是唯一的,但不是順序:

i=1; while read line; do echo ${line/\./.$((i++))}; done < input 

1 .1 Fred 1 6 78 8 09 
1 1 Geni 1 4 68 9 34 
2 .3 Sam 3 4 56 6 89 
3 .4 Flit 2 4 56 8 34 
3 4 Dog 2 5 67 8 78 
3 .6 Pig 2 5 67 2 21 

擊+ sed的

sed不能增加變量,它必須在外部進行。

對於每一行,增加$i如果行包含.,然後讓sed.

i=0          
while read line; do     
    [[ $line == *.* ]] && i=$((i+1)) 
    sed "s#\.#.$i#" <<<"$line" 
done < input       

輸出後追加$i

1 .1 Fred 1 6 78 8 09 
1 1 Geni 1 4 68 9 34 
2 .2 Sam 3 4 56 6 89 
3 .3 Flit 2 4 56 8 34 
3 4 Dog 2 5 67 8 78 
3 .4 Pig 2 5 67 2 21