2 votes

Comment utiliser sed avec des variables de chemin de fichier ET des rappels de regex ET des expressions arithmétiques

J'ai beaucoup de mal à obtenir la bonne syntaxe en utilisant sed avec des variables contenant un chemin de fichier, un callback regex et une expression arithmétique. Je ne sais pas comment échapper correctement les choses.

J'ai un chemin de fichier dans un fichier texte avec un numéro à côté. Je veux trouver cette ligne et incrémenter le numéro.

FILE="/home/username/scripts/test.txt"
LINE="/home/username/Pictures/properties/wallpaper/span/tree.jpg"

sed -i -e "s,'$LINE' \([0-9]*\),'$LINE' $((\1+1))," $FILE

Par exemple

/home/username/Pictures/properties/wallpaper/span/tree.jpg 2

devrait devenir..

/home/username/Pictures/properties/wallpaper/span/tree.jpg 3

Quelle est la meilleure façon d'échapper au "." dans le chemin du fichier ? Comment mettre en œuvre correctement la fonction \1 et l'expression arithmétique $((\1+1) ?

Actuellement, je reçois un mauvais jeton \1+1 erreur.

3voto

user221266 Points 11

sed et l'arithmétique ne font pas bon ménage. Le bon outil pour ce genre de travail est awk .

Considérez ce fichier de test :

$ cat test.txt
/nonmatching/line 1
/home/username/Pictures/properties/wallpaper/span/tree.jpg 2
/another/non/matching/line 5

On peut incrémenter le numéro de la ligne que vous voulez avec :

$ line="/home/username/Pictures/properties/wallpaper/span/tree.jpg"
$ awk -v f="$line" '$0~f {$NF++} 1' test.txt
/nonmatching/line 1
/home/username/Pictures/properties/wallpaper/span/tree.jpg 3
/another/non/matching/line 5

Comme vous pouvez le voir, cela a incrémenté le nombre sur la ligne qui correspondait $line .

Une limitation est que ce code, tel qu'il est écrit, ne préservera pas les blancs multiples sur les lignes pour lesquelles le nombre est incrémenté. Si les espaces blancs sont importants, il faudrait définir davantage le format d'entrée.

Comment cela fonctionne

  • -v f="$line"

    Ceci assigne la valeur de la variable Shell. line à la variable awk f .

  • $0~f {$NF++}

    Ici, $0~f est une condition. Elle est vraie si la ligne d'entrée, notée $0 correspond au regex f comme défini ci-dessus. Si elle correspond, alors la déclaration $NF++ est exécuté. Cela incrémente le dernier champ de la ligne qui, pour votre entrée, est le nombre.

  • 1

    C'est le raccourci cryptique d'awk pour imprimer la ligne.

Modifier un fichier sur place avec awk

Si vous avez un GNU awk moderne, vous pouvez éditer le fichier en place avec :

gawk -i inplace -v f="$line" '$0~f {$NF++} 1' test.txt

Avec d'autres awks, utilisez :

awk -v f="$line" '$0~f {$NF++} 1' test.txt > tmp.txt && mv -f tmp.txt test.txt

Créer text.txt s'il n'existe pas

Dans le cas où le fichier test.txt ne contient pas de ligne correspondant à $line cette version sera une telle ligne avec 1 pour le comptage :

gawk -i inplace -v f="$line" '$0~f {n=1; $NF++} 1; END{if(!n) print f,1>>FILENAME}' test.txt

Ce code ajoute une variable n . Si $line est dans le dossier, n est réglé sur 1 . Si ce n'est pas le cas, n reste à la valeur par défaut de 0 . Au END du fichier d'entrée, la valeur de n est testé. Si n est encore nulle, la ligne est ajoutée.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X