2012-12-19 53 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

相关问题