2012-12-19 44 views
6

Tôi muốn thay thế chuỗi TaskID_1 bằng một chuỗi bắt đầu từ 1001TaskID_1 này có thể tồn tại nhiều số dòng trong tệp nhập của tôi. Tương tự, tôi cần thay thế tất cả các lần xuất hiện của TASKID_2 trong tệp nhập của tôi với giá trị chuỗi tiếp theo 1002.Thay thế mẫu chuỗi bằng một chuỗi khác trong unix

tập tin đầu vào:

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 

Các tập tin đầu ra sẽ giống như thế:

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 

Trả lời

9

Dưới đây là một trong những cách sử dụng awk:

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

Hoặc ít một cách chi tiết:

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

Kết quả:

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 

Đối với ví dụ đầu tiên, tách tập tin và tập tin đầu ra tách được thiết lập để một nhân vật ống duy nhất. Điều này được đặt trong khối BEGIN, do đó nó được thực hiện chỉ một lần, và không phải trên mỗi dòng đầu vào. Sau đó, chúng tôi đặt cột thứ ba bằng 1000 cộng với biến gia tăng. Chúng tôi có thể sử dụng ++i làm biến này, nhưng thay vào đó chúng tôi có thể sử dụng NR (viết tắt của số lượng/số dòng) và điều này sẽ tránh được sự cần thiết phải tạo thêm biến. 1 ở cuối cho phép in theo mặc định. Một giải pháp tiết hơn sẽ trông giống như:

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

EDIT:

Sử dụng các tập tin dữ liệu được cập nhật, hãy thử:

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

Kết quả:

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 ** ... yup, đó chỉ là về chính xác làm thế nào tôi muốn làm điều đó. – ghoti

+1

+1 darn, đánh bại tôi với nó (giải pháp cuối cùng ở trên, đó là) :-). –

+1

Cảm ơn Steve .. Giải pháp này hoạt động rất tốt. – Ramkumar

2

Tôi không thể đưa ra một giải pháp tốt hơn so với một trong những đề nghị trong awk.

Vì vậy, đây là giải pháp tồi tệ hơn, chỉ sử dụng 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 

Đó là "tồi tệ" chỉ vì nó sẽ chậm hơn nhiều so với awk, nhanh và hiệu quả với loại vấn đề này.

+0

Thời gian cho một tệp có 1M dòng: 66 giây. Rất chậm, nhưng vẫn ok để sử dụng và dễ hiểu. – erik

+0

Nếu bạn thay thế $ ((++ n)) theo $ (($ {f3 # * _} + 1000)) thì đó là câu hỏi mong muốn. Và thời gian tôi đo là cho phiên bản sửa chữa. – erik

+0

Ồ, và bạn phải thay thế 'f1 f2 _ f4 f5 f6' bằng' f1 f2 f3 f4 f5 f6'. – erik

4

dung dịch A Perl sử dụng logic của việc thêm 1000 của Steve:

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

này thay thế 'TaskID_n' với 1000 + n. 'e' được sử dụng để đánh giá sự thay thế.

+0

Thời gian cho một tệp có 1M dòng: 6.363 giây. Một chút chậm hơn so với awk nhưng dễ hiểu hơn nếu bạn biết các biểu thức chính quy. – erik

1

Thay TaskID_ với 100, đây là siêu dễ dàng với sed cho ID chữ số duy nhất:

$ 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 

Để lưu thay đổi này trở lại các tập tin sử dụng -i tùy chọn:

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

Lưu ý: điều này làm việc cho TaskID_[0-9] nếu bạn muốn TaskID_23 ánh xạ tới 1023 thì điều này sẽ không, điều này sẽ lập bản đồ TaskID_23 đến 10023.

+1

Thời gian cho một tệp có 1M dòng: 0.861 giây. Nhanh nhất, nhưng chỉ cho 1000 đến 1009. – erik

+0

@erik làm việc tốt, tôi thấy điểm chuẩn của bạn rất thú vị. –

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

Tested Dưới:

> 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

Thời gian cho một tệp có 1M dòng: 7.463 giây. Chậm nhất (ngoại trừ bash), và chỉ cho 1000 đến 1009. – erik

Các vấn đề liên quan