2012-12-19 48 views
6

我想用從1001開始的序列替換字符串TaskID_1,並且此TaskID_1可以在我的輸入文件中存在任意數量的行。 同樣,我需要用我的輸入文件中的所有匹配項TASKID_2替換下一個序列值1002用unix中的另一個序列替換字符串模式

輸入文件:

12345|45345|TaskID_1|dksj|kdjfdsjf|12 
1245|425345|TaskID_1|dksj|kdjfdsjf|12 
1234|25345|TaskID_2|dksj|kdjfdsjf|12 
123425|65345|TaskID_2|dksj|kdjfdsjf|12 
123425|15325|TaskID_1|dksj|kdjfdsjf|12 
11345|55315|TaskID_2|dksj|kdjfdsjf|12 
6345|15345|TaskID_3|dksj|kdjfdsjf|12 
72345|25345|TaskID_4|dksj|kdjfdsjf|12 
9345|411345|TaskID_3|dksj|kdjfdsjf|12 

輸出文件應該是這樣:

12345|45345|1001|dksj|kdjfdsjf|12 
1245|425345|1001|dksj|kdjfdsjf|12 
1234|25345|1002|dksj|kdjfdsjf|12 
123425|65345|1002|dksj|kdjfdsjf|12 
123425|15325|1001|dksj|kdjfdsjf|12 
11345|55315|1002|dksj|kdjfdsjf|12 
6345|15345|1003|dksj|kdjfdsjf|12 
72345|25345|1004|dksj|kdjfdsjf|12 
9345|411345|1003|dksj|kdjfdsjf|12 

回答

9

下面是使用awk一個辦法:

awk 'BEGIN { FS=OFS="|" } { $3=1000 + NR }1' file 

或者更少的冗長:

awk -F '|' '{ $3=1000 + NR }1' OFS='|' file 

結果:

12345|45345|1001|dksj|kdjfdsjf|12 
1245|425345|1002|dksj|kdjfdsjf|12 
1234|25345|1003|dksj|kdjfdsjf|12 
123425|65345|1004|dksj|kdjfdsjf|12 
123425|15325|1005|dksj|kdjfdsjf|12 
11345|55315|1006|dksj|kdjfdsjf|12 
6345|15345|1007|dksj|kdjfdsjf|12 
72345|25345|1008|dksj|kdjfdsjf|12 
9345|411345|1009|dksj|kdjfdsjf|12 

對於第一個示例中,文件分離器和輸出文件隔板設置爲單個管字符。這在BEGIN塊中設置,因此它只執行一次,而不是每行輸入。然後我們將第三列設置爲等於1000加上增量變量。我們可以使用++i作爲這個變量,但我們可以改爲使用NR(這是記錄號/行號的縮寫),因此可以避免創建額外變量。最後的1默認啓用打印。一個更詳細的解決辦法是這樣的:

awk 'BEGIN { FS=OFS="|" } { $3=1000 + NR; print }' file 

編輯:

使用更新後的數據文件,請嘗試:

awk 'BEGIN { FS=OFS="|" } { sub(/.*_/,"",$3); $3+=1000 }1' file 

結果:

12345|45345|1001|dksj|kdjfdsjf|12 
1245|425345|1001|dksj|kdjfdsjf|12 
1234|25345|1002|dksj|kdjfdsjf|12 
123425|65345|1002|dksj|kdjfdsjf|12 
123425|15325|1001|dksj|kdjfdsjf|12 
11345|55315|1002|dksj|kdjfdsjf|12 
6345|15345|1003|dksj|kdjfdsjf|12 
72345|25345|1004|dksj|kdjfdsjf|12 
9345|411345|1003|dksj|kdjfdsjf|12 
+1

** + 1 ** ......是啊,這只是關於到底我會做到這一點。 – ghoti

+1

+1 darn,打我吧(上面的最後一個解決方案,那就是):-)。 –

+1

謝謝Steve ..這個解決方案很好用。 – Ramkumar

2

我不能想出一個比awk中的steve更好的解決方案。

所以這裏是一個糟糕的解決方案,只使用bash。

#!/bin/bash 

IFS='|' 

while read f1 f2 f3 f4 f5 f6; do 
    printf '%s|%s|%d|%s|%s|%s\n' "$f1" "$f2" "$((${f3#*_}+1000))" "$f4" "$f5" "$f6" 
done < input 

它只是「更糟」,因爲它比awk慢很多,這對於這類問題來說是快速有效的。使用加入1000的史蒂夫的邏輯

+0

1M行文件的時間:66秒。非常緩慢,但仍然可以使用和易於理解。 – erik

+0

如果用$(($ {f3#* _ + 1000))替換$((++ n))),那麼這就是問題所在。而我測量的時間是修正版本。 – erik

+0

哦,你必須用'f1 f2 f3 f4 f5 f6'來代替'f1 f2 _ f4 f5 f6'。 – erik

4

一個Perl溶液:

perl -pne 's/TaskID_(\d+)/$1+1000/e;' file 

這取代了 'TaskID_n' 1000 + N。 'e'用於評估替換。

+0

1M行文件的時間:6.363秒。比awk慢一些,但如果你知道正則表達式則更容易理解。 – erik

1

更換TaskID_100,這與sed爲個位數的ID超級簡單:

$ sed 's/TaskID_/100/' file 
12345|45345|1001|dksj|kdjfdsjf|12 
1245|425345|1001|dksj|kdjfdsjf|12 
1234|25345|1002|dksj|kdjfdsjf|12 
123425|65345|1002|dksj|kdjfdsjf|12 
123425|15325|1001|dksj|kdjfdsjf|12 
11345|55315|1002|dksj|kdjfdsjf|12 
6345|15345|1003|dksj|kdjfdsjf|12 
72345|25345|1004|dksj|kdjfdsjf|12 
9345|411345|1003|dksj|kdjfdsjf|12 

存儲該變回文件使用-i選項:

sed -i 's/TaskID_/100/' file 

注:這適用於TaskID_[0-9]如果你想TaskID_23映射到1023那麼這不會,這將映射TaskID_2310023

+1

1M行文件的時間:0.861秒。最快,但只有1000至1009. – erik

+0

@erik很好的工作,我發現你的基準非常有趣。 –

0
perl -F"\|" -lane '$F[2]=~s/.*_/100/g;print join("|",@F)' your_file 

以下測試:

> cat temp 
12345|45345|TaskID_1|dksj|kdjfdsjf|12 
1245|425345|TaskID_1|dksj|kdjfdsjf|12 
1234|25345|TaskID_2|dksj|kdjfdsjf|12 
123425|65345|TaskID_2|dksj|kdjfdsjf|12 
123425|15325|TaskID_1|dksj|kdjfdsjf|12 
11345|55315|TaskID_2|dksj|kdjfdsjf|12 
6345|15345|TaskID_3|dksj|kdjfdsjf|12 
72345|25345|TaskID_4|dksj|kdjfdsjf|12 
9345|411345|TaskID_3|dksj|kdjfdsjf|12 
> perl -F"\|" -lane '$F[2]=~s/.*_/100/g;print join("|",@F)' temp 
12345|45345|1001|dksj|kdjfdsjf|12 
1245|425345|1001|dksj|kdjfdsjf|12 
1234|25345|1002|dksj|kdjfdsjf|12 
123425|65345|1002|dksj|kdjfdsjf|12 
123425|15325|1001|dksj|kdjfdsjf|12 
11345|55315|1002|dksj|kdjfdsjf|12 
6345|15345|1003|dksj|kdjfdsjf|12 
72345|25345|1004|dksj|kdjfdsjf|12 
9345|411345|1003|dksj|kdjfdsjf|12 
> 
+0

1M行文件的時間:7.463秒。最慢(除了bash),只有1000到1009。 – erik

相關問題