用unix中的另一个序列替换字符串模式

时间:2012-12-19 12:16:09

标签: unix awk

我想用从TaskID_1开始的序列替换字符串1001,并且此TaskID_1可以在我的输入文件中存在任意多行。 同样,我需要使用下一个序列值TASKID_2替换输入文件中出现的所有1002

输入文件:

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

5 个答案:

答案 0 :(得分: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 :(得分:4)

使用史蒂夫添加1000的逻辑的Perl解决方案:

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

这将'TaskID_n'替换为1000 + n。 'e'用于评估替换。

答案 2 :(得分:2)

我无法想出一个比awk中建议的史蒂夫更好的解决方案。

所以这是一个更糟糕的解决方案,只使用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慢得多,而这种问题快速有效。

答案 3 :(得分:2)

TaskID_替换为100,对于单个数字ID,sed非常简单:

$ 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_23映射到10023 }。

答案 4 :(得分: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
>