Tente isso (é necessário um gawk).
awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}' YourFile
Teste com seu exemplo:
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"))
)
Observe que este comando não funcionará se os dois números (por exemplo, 1 "e" # 1 ") forem diferentes ou se houver mais números na mesma linha com esse padrão (por exemplo, 23" ... 32 "..." # 123 ") em uma linha.
ATUALIZAR
Desde @Tim (OP) disse que o número seguido por "
mesma linha poderia ser diferente, fiz algumas alterações na minha solução anterior e a fiz funcionar no seu novo exemplo.
BTW, a partir do exemplo, sinto que poderia ser uma tabela de estrutura de conteúdo, então não vejo como os dois números podem ser diferentes. Primeiro seria o número da página impressa e o segundo com # seria o índice da página. Estou certo?
Enfim, você conhece melhor sua exigência. Agora a nova solução, ainda com gawk (eu quebro o comando em linhas para facilitar a leitura):
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
teste com seu novo exemplo:
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 com base no comentário de @Tim
(1) FS = OFS = "\" \ "#" significa que o separador de campo na entrada e na saída é aspas duplas, espaço, aspas duplas e #? Por que especificar aspas duplas duas vezes?
Você está certo para o separador na parte de entrada e saída. Definiu separador como:
" "#
Existem duas aspas duplas, porque é mais fácil capturar os dois números que você deseja (com base em sua entrada de exemplo).
(2) Em /.* ([0-9] +) $ /, $ significa o final da string?
Exatamente!
(3) No terceiro argumento de gensub (), qual é a diferença entre "g" e "G"? não há diferença entre G e g. Veja isso:
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.
Isto é de http://www.gnu.org/s/gawk/manual/html_node/String-Functions.html . você pode ler para obter um uso detalhado do gensub.