Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Équivalent d'une commande mais avec awk au lieu de sed

12 réponses
Avatar
Francois Lafont
Bonjour à tous,

Je ne suis vraiment pas un expert en sed et en awk. Quand il faut faire
une petite substitution dans un fichier j'utilise sed et quand c'est
plus compliqué je passe à awk (non sans l'aide de Google ou autre).


1. Pouvez-vous me donner l'équivalent de la commande ci-dessous mais en
utilisant awk au lieu de sed ?

sed -r \
-e 's/^var[[:space:]]*=[[:space:]]*(.*)[[:space:]]*$'/\1/g' \
fichier

La regex choisie est un exemple, ça pourrait être autre chose. En
cherchant dans la page man de awk, j'ai trouvé comme équivalent ceci :

awk '{
c=gensub("^var[[:space:]]*=[[:space:]]*(.*)[[:space:]]*$", "\\1", "g")
print c
}' fichier

a) Est-ce que cela vous paraît être un équivalent correct ?
b) N'y a-t-il pas plus simple quand même ?


2) Dans la commande juste au dessus (celle avec awk), j'ai voulu
remplacer la fonction gensub() par gsub() mais en vain. Par exemple,
ceci :

awk '{
gsub("^var[[:space:]]*=[[:space:]]*(.*)[[:space:]]*$", "\\1")
print c
}' fichier

m'affiche « \1 » au lieu de m'afficher le premier sous-groupe dans ma
regex (comme c'est le avec gensub). Pourquoi ?


3) Enfin, connaissez-vous un équivalent avec awk de la commande de la
question 1 à laquelle j'ajoute l'option -i (bien pratique je trouve) ?
Autrement dit un équivalent avec awk de ça :

sed -i -r -e 's/regex/remplacement/g' fichier

Je ne vois pas d'autre moyen que de faire ça :

awk '{ c=gensub("regex", "remplacement", "g"); print c }' \
fichier > /tmp/fichier_temp
cat fichier_temp > fichier
rm /tmp/fichier_temp

ce qui est tout de même beaucoup plus bavard.

Merci pour votre aide.

--
François Lafont

2 réponses

1 2
Avatar
Benoit Izac
Bonjour,

le 05/09/2012 à 11:38, Marc Boyer a écrit dans le message
<k276hv$fkk$ :

Un truc du genre (non teste):
SRC=`basename fichier`
RES=`mktemp XXX-$SRC`
BACKUP=`mktemp XXX-${SRC}~`

awk '{....}' fichier > $RES
if [ "$?" == "0" ]; then
mv fichier ${BACKUP}
mv ${RES} fichier
fi

Mais pour êre vraiment robuste, faudrait aussi tester que les mv
fonctionnent, et essayer de revenir en arrière....
On pourrait être plus prudent et faire un cp à la place du premier mv.



Pourquoi revenir en arrière alors « fichier » ne sera pas modifié avant
la dernière commande ? De plus, il existe « set -e » pour ne pas
s'embêter à faire des tests après chaque commande.

--
Benoit Izac
Avatar
Francois Lafont
Le 05/09/2012 11:38, Marc Boyer a écrit :

Ça m'intéresserait bien de savoir à quoi ça ressemblerait avec des tests
« bétonnés de chez bétonnés » ? À ça ?

awk '{ c=gensub("regex", "remplacement", "g"); print c }'
fichier > /tmp/fichier_temp



Faut déjà générer un num de fichier unique (avec mktemp ou un copain).
Ensuite, oui, tester la valeur de retour de awk (mais bon, un petit &&
devrait suffire).
Et moi, je prendrais ensuite un mv plutôt qu'un cat.
Si les deux fichiers sont sur la même partition, mv devrait ne pas
copier le contenu du fichier, mais uniquement changer des infos d'emplacement
et de nommage.

Un truc du genre (non teste):
SRC=`basename fichier`
RES=`mktemp XXX-$SRC`
BACKUP=`mktemp XXX-${SRC}~`

awk '{....}' fichier > $RES
if [ "$?" == "0" ]; then
mv fichier ${BACKUP}
mv ${RES} fichier
fi

Mais pour êre vraiment robuste, faudrait aussi tester que les mv
fonctionnent, et essayer de revenir en arrière....
On pourrait être plus prudent et faire un cp à la place du premier mv.



Ok, effectivement un mv, si on est sur la même partition, est plus
pertinent.

Je pose la question parce que je me dis qu'au final on peut ne pas en
voir le bout des tests si on pousse la prudence à l'extrême (par
exemple, qu'est-ce qui me prouve qu'entre la commande "awk" et la
commande "cat" le fichier fichier_temp ne va pas subir une modification
intempestive de je ne sais quel programme ?).



Ce problème existera aussi avec sed -i.



Ok, merci bien Marc pour la réponse.

--
François Lafont
1 2