Hãy thử điều này (gawk là cần thiết).
awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}' YourFile
Kiểm tra với ví dụ của bạn:
kent$ echo '(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 2" "#2")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)
'|awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}'
(bookmarks
("Chapter 1 Introduction 12" "#12"
("1.1 Problem Statement and Basic Definitions 13" "#13")
("Exercises 41" "#41")
("Notes and References 45" "#45"))
)
Lưu ý rằng lệnh này sẽ không hoạt động nếu hai số (ví dụ 1 "và" # 1 ") khác nhau hoặc có nhiều số hơn cùng dòng với mẫu này (ví dụ: 23" ... 32 "..." # 123 ") trong một dòng.
CẬP NHẬT
Vì @Tim (OP) cho biết số theo sau "
trong cùng một dòng có thể khác nhau, tôi đã thực hiện một số thay đổi trên giải pháp trước đây của mình và làm cho nó hoạt động cho ví dụ mới của bạn.
BTW, từ ví dụ tôi cảm thấy rằng nó có thể là một bảng cấu trúc nội dung, vì vậy tôi không thấy hai con số có thể khác nhau như thế nào. Đầu tiên sẽ là số trang in và thứ 2 với # sẽ là chỉ mục trang. Tôi có đúng không
Dù sao, bạn biết yêu cầu của bạn tốt nhất. Bây giờ là giải pháp mới, vẫn với gawk (Tôi chia lệnh thành các dòng để dễ đọc hơn):
awk 'BEGIN{FS=OFS="\" \"#"}{if(NF<2){print;next;}
a=gensub(/.* ([0-9]+)$/,"\\1","g",$1);
b=gensub(/([0-9]+)\"/,"\\1","g",$2);
gsub(/[0-9]+$/,a+11,$1);
gsub(/^[0-9]+/,b+11,$2);
print $1,$2
}' yourFile
kiểm tra với ví dụ mới của bạn :
kent$ echo '(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 23" "#2")
("Exercises 31" "#30")
("Notes and References 42" "#34"))
)
'|awk 'BEGIN{FS=OFS="\" \"#"}{if(NF<2){print;next;}
a=gensub(/.* ([0-9]+)$/,"\\1","g",$1);
b=gensub(/([0-9]+)\"/,"\\1","g",$2);
gsub(/[0-9]+$/,a+11,$1);
gsub(/^[0-9]+/,b+11,$2);
print $1,$2
}'
(bookmarks
("Chapter 1 Introduction 12" "#12"
("1.1 Problem Statement and Basic Definitions 34" "#13")
("Exercises 42" "#41")
("Notes and References 53" "#45"))
)
EDIT2 dựa trên nhận xét của @Tim
(1) Có phải FS = OFS = "\" \ "#" có nghĩa là dấu phân cách của trường trong cả đầu vào và đầu ra là trích dẫn kép, dấu cách, dấu ngoặc kép và #? Tại sao chỉ định trích dẫn hai lần?
Bạn đúng cho dấu phân cách ở cả phần đầu vào và đầu ra. Nó định nghĩa dấu phân cách là:
" "#
Có hai dấu ngoặc kép, vì sẽ dễ dàng hơn để bắt được hai số bạn muốn (dựa trên đầu vào ví dụ của bạn).
(2) Trong /.* ([0-9] +) $ /, $ có nghĩa là kết thúc chuỗi không?
Chính xác!
(3) Trong đối số thứ ba của gensub (), sự khác biệt giữa "g" và "G" là gì? không có sự khác biệt giữa G và g. Kiểm tra này:
gensub(regexp, replacement, how [, target]) #
Search the target string target for matches of the regular expression regexp.
If "how" is a string beginning with ‘g’ or ‘G’ (short for “global”), then
replace all matches of regexp with replacement.
Đây là từ http://www.gnu.org/s/gawk/manual/html_node/String-Fiances.html . bạn có thể đọc để có được cách sử dụng chi tiết của gensub.