Diminuer un nombre avec sed

J'ai extrait les métadonnées d'un file PDF dans un file .txt en utilisant pdftk , et maintenant j'essaie de diminuer la valeur de l'élément BookmarkPageNumber pour chaque signet par un entier. Le .txt a ces lignes:

 BookmarkBegin BookmarkTitle: Preface BookmarkLevel: 1 BookmarkPageNumber: 10 BookmarkBegin BookmarkTitle: Author ... and so on 

J'essaie de faire ceci en utilisant la command de substitution de sed, et voici ce que j'ai jusqu'à présent:

 // $1 is the source .txt file; $2 is the decrement // __ is a placeholder for the variable with the original value cat $1 | sed "s/BookmarkPageNumber: [0-9]*/BookmarkPageNumber: `expr __ - $2`/" | cat > metadata.txt 

Ma question est: comment puis-je mettre la valeur originale dans une variable, puis replace le palceholder __ avec elle, dans cette même expression sed?

Je suis nouveau pour bash scripting, et je m'excuse si je pose les mauvaises questions.

Je vous remercie.

A cette fin, il vaut mieux utiliser awk pour supporter les opérations arithmétiques

 cat $1 | awk -vd=$2 '/BookmarkPageNumber:/{$2-=d}1' 
 awk '!/BookmarkPageNumber:/ {print}; /BookmarkPageNumber:/ {print $1 " " $2-1}' old.txt > new.txt 

Un autre choix serait d'utiliser le shell lui-même (en utilisant le 5 comme exemple, changez-le en l'entier que vous voulez soustraire):

 while read key val; do [[ $key == "BookmarkPageNumber:" ]] && let val=val-5; echo $key $val; done < file 

Ou, vous pourriez utiliser un outil comme perl :

 perl -pe 's/(BookmarkPageNumber:\s*)(\d+)$/$1 . ($2-5)/e; ' file 

Et voici une autre approche awk :

 awk '$1~/BookmarkPageNumber:/{$2=$2-5}1;' file 

NOTE: Je viens de réaliser qu'il voulait diminuer le nombre de signets par un integer arbitraire que j'ai initialement ignoré et que ma solution ci-dessous ne fonctionne que pour la diminuer de 1. Cependant, je me sens mal à l'aise en considérant les efforts que je fais:

——– solution partielle seulement ———

Au cas où vous ne seriez pas prêt à utiliser sed, j'ai ce 1 doublure pour vous: sed -r '/^BookmarkPageNumber: /{s/([0-9]*)$/\1@/;:loop {s/0@/@9/;/0@/b loop;};s/1@/_0/;s/2@/_1/;s/3@/_2/;s/4@/_3/;s/5@/_4/;s/6@/_5/;s/7@/_6/;s/8@/_7/;s/9@/_8/;s/ @9+$/ UNDERFLOW/;s/ _0*/ /;s/_//}' $1 >metadata.txt

Note: cela ne fonctionne que pour les nombres décimaux naturels, j'espère que cela vous convient.

Oh, il a même une détection de sous-écoulement. Donc, au cas où vous voudriez que vos numéros de page soient saturés à 0, remplacez simplement UNDERFLOW par 0

Et je suis d'accord avec quiconque qualifie cela d'une branle intellectuelle, parce que c'est ce que c'est.

ps: Vous devriez probablement vérifier que vos descripteurs de files d'input et de sortie ne pointent pas sur le même file, sinon le file sera tronqué si l'user a un access en écriture.