Essayez ceci (gawk est nécessaire).
awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}' YourFile
Testez avec votre exemple:
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"))
)
Notez que cette commande ne fonctionnera pas si les deux nombres (par exemple 1 "et" # 1 ") sont différents. Ou s'il y a plus de nombres sur la même ligne avec ce modèle (par exemple 23" ... 32 "..." # 123 ") sur une seule ligne.
MISE À JOUR
Étant donné que @Tim (OP) a déclaré que le nombre suivi de la "
même ligne pourrait être différent, j'ai apporté quelques modifications à ma solution précédente et l'ai fait fonctionner pour votre nouvel exemple.
BTW, d'après l'exemple, je pense que cela pourrait être une table de structure de contenu, donc je ne vois pas comment les deux nombres pourraient être différents. Le premier serait le numéro de page imprimé, et le deuxième avec # serait l'index de la page. Ai-je raison?
Quoi qu'il en soit, vous connaissez le mieux vos besoins. Maintenant la nouvelle solution, toujours avec gawk (je décompose la commande en lignes pour en faciliter la lecture):
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
tester avec votre nouvel exemple:
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 basé sur le commentaire de @Tim
(1) FS = OFS = "\" \ "#" signifie-t-il que le séparateur de champ en entrée et en sortie est un guillemet double, un espace, un guillemet double et #? Pourquoi spécifier deux fois le guillemet double?
Vous avez raison pour le séparateur à la fois en entrée et en sortie. Il définit le séparateur comme:
" "#
Il y a deux guillemets doubles, car il est plus facile d'attraper les deux nombres que vous souhaitez (en fonction de votre exemple d'entrée).
(2) Dans /.* ([0-9] +) $ /, $ signifie-t-il la fin de la chaîne?
Exactement!
(3) Dans le troisième argument de gensub (), quelle est la différence entre "g" et "G"? il n'y a pas de différence entre G et g. Regarde ça:
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.
Il s'agit de http://www.gnu.org/s/gawk/manual/html_node/String-Functions.html . vous pouvez lire pour obtenir une utilisation détaillée de gensub.