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

[sed ou awk] 's/n1:n2/n1*cste+n2/g'

8 réponses
Avatar
David LE BOURGEOIS
Bonjour à tous,

J'ai une petite question pour une substitution.
Est-il possible de remplacer toutes les occurences de 'n1:n2' par
'n1*cste+n2' dans un ensemble de données ?

n1, n2 et cste sont des entiers positifs, donc correspondent à
'[0-9]*'. Mais le problème est de reconnaître la forme 'n1:n2' dans la
ligne, car elle fait partie d'un texte, et donc entourrée de tous les
caractères possibles. Sinon, je ne poserais pas la question :-).

Je sais qu'il doit est possible de le faire avec les outils lex/yacc,
mais ça fait longtemps que je les ai pratiqués. Alors, n'existe-t-il pas
une solution avec sed ? ou avec awk (pour calculer la valeur de
l'expression) ?
Sinon, tant pis, je replonge dans mes manuels de lex.

Merci d'avance pour vos réponses.

David.

8 réponses

Avatar
Stephane CHAZELAS
Le Fri, 03 Oct 2003 16:08:00 +0200, David LE BOURGEOIS écrivait :
[...]
J'ai une petite question pour une substitution.
Est-il possible de remplacer toutes les occurences de 'n1:n2' par
'n1*cste+n2' dans un ensemble de données ?


perl -pe 's/(d+):(d+)/$1 * 3.14 + $2/eg'

Avec awk, c'est beaucoup plus fastidieux (faut jouer avec
"match" [avec RLENGTH] et des substr et des split)

Quelque chose comme:

awk '/[0-9]:[0-9]/{
a=$0; b=""
while (match(a, /[0-9][0-9]*:[0-9][0-9]*/)) {
split(substr(a, RSTART, RLENGTH), f, ":")
b=b substr(a, 1, RSTART-1) f[1] * 3.14 + f[2]
a=substr(a, RSTART + RLENGTH)
}
$0=b}1'

Avec sed, c'est possible aussi, mais ça sera pas pour ce soir.

--
Stéphane

Avatar
Stephane CHAZELAS
Le 03 Oct 2003 17:46:28 GMT, Stephane CHAZELAS écrivait :
[...]
Avec awk, c'est beaucoup plus fastidieux (faut jouer avec
"match" [avec RLENGTH] et des substr et des split)

Quelque chose comme:
[...]


Plutot comme:

awk '/[0-9]:[0-9]/{
a=$0; b=""
while (match(a, /[0-9][0-9]*:[0-9][0-9]*/)) {
split(substr(a, RSTART, RLENGTH), f, ":")
b=b substr(a, 1, RSTART-1) f[1] * 3.14 + f[2]
a=substr(a, RSTART + RLENGTH)
}
$0=b a}1'

--
Stéphane

Avatar
Stephane CHAZELAS
Le Sat, 04 Oct 2003 22:35:39 +0200, Marc Lasson écrivait :
Stephane CHAZELAS wrote:

Avec sed, c'est possible aussi, mais ça sera pas pour ce soir.


[...]

sortie:

gnagnagna 3.0 * cte + 2.0 a.b gnagnagna


Oui, mais non, David voulait en sortie le résultat du calcul.
i.e. avec cte = 3.14:

« gnagnagna 11.42 a.b gnagnagna »

comme dans les solutions perl ou awk que je donnai.

Et là, ça devient beaucoup plus balèze avec sed, voir
http://sed.sourceforge.net/grabbag/scripts/dc_overview.htm
pour des pistes.

--
Stéphane


Avatar
Marc Lasson
Stephane CHAZELAS wrote:

Avec sed, c'est possible aussi, mais ça sera pas pour ce soir.


Allez, un effort :)

Je suis débutant en sed, alors ca risque pas d'etre optimum.


echo "gnagnagna 2:666 a.b gnagnagna" | sed -e

"s/([0-9]+):([0-9]+)/1 * cte + 2/g"

si tu veux matcher les réels aussi:

"s/([0-9]+.+[0-9]*):([0-9]+.+[0-9]*)/1 * cte + 2/g"

Je ne suis pas sur de la portabilité du "+", on peut le remplacer
par "{1,}".

sortie:

gnagnagna 3.0 * cte + 2.0 a.b gnagnagna

--
Marc.

Avatar
Marc Lasson
Stephane CHAZELAS wrote:
[...]
Avec sed, c'est possible aussi, mais ça sera pas pour ce soir.


Allez, un effort :)

Je suis débutant en sed, alors ca risque pas d'etre optimum.

echo "gnagnagna 2:666 a.b gnagnagna" | sed -e

"s/([0-9]+):([0-9]+)/1 * cte + 2/g"

si tu veux matcher les réels aussi:

"s/([0-9]+.+[0-9]*):([0-9]+.+[0-9]*)/1 * cte + 2/g"

Je ne suis pas sur de la portabilité du "+", on peut le remplacer
par "{1,}".

sortie:

gnagnagna 3.0 * cte + 2.0 a.b gnagnagna

Avatar
Pascal Bourguignon
Stephane CHAZELAS writes:
Et là, ça devient beaucoup plus balèze avec sed, voir
http://sed.sourceforge.net/grabbag/scripts/dc_overview.htm
pour des pistes.


Oui, ça devient balèze avec sed, mais c'est tout à fait possible: sed
est une machine de Turing.

Voici par exemple, une addition binaire en sed. Le reste est trivial
(conversion binaire/décimal, multiplication, etc).

#!/bin/bash
trace #trace=p
for sum in '101101 + 10100' '1+1111111' '10101010+01010101' ; do
echo $sum | sed -e 's/ //g' -e 's/$/=/' -e "{
t next-digit
:next-digit
s/^[+]=//$trace
t end
s/^([01][01]*)[+]=(.*)$/12/$trace
t end
s/^[+]([01][01]*)=(.*)$/12/$trace
t end
s/^([01]*)0[+]([01]*)0=(.*)$/1+2/$trace
t next-digit
s/^([01]*)1[+]([01]*)0=(.*)$/1+2/$trace
t next-digit
s/^([01]*)0[+]([01]*)1=(.*)$/1+2/$trace
t next-digit
s/^([01]*)1[+]([01]*)1=(.*)$/1+2/$trace
t sum-carry
b error
:sum-carry
s/^[+]=/1/$trace
t end
s/^([01][01]*)[+]=(.*)$/12/$trace
t end
s/^[+]([01][01]*)=(.*)$/12/$trace
t end
s/^([01]*)0[+]([01]*)0=(.*)$/1+2/$trace
t next-digit
s/^([01]*)1[+]([01]*)0=(.*)$/1+2/$trace
t sum-carry
s/^([01]*)0[+]([01]*)1=(.*)$/1+2/$trace
t sum-carry
s/^([01]*)1[+]([01]*)1=(.*)$/1+2/$trace
t sum-carry
:error
s/^/ERROR: /$trace
:end
s/^/SUM=/$trace
}"
done
#### turing.sed -- 2003-10-05 12:03:42 -- pascal ####


--
__Pascal_Bourguignon__
http://www.informatimago.com/
Do not adjust your mind, there is a fault in reality.

Avatar
Stephane CHAZELAS
Le 05 Oct 2003 12:06:04 +0200, Pascal Bourguignon écrivait :
Stephane CHAZELAS writes:
Et là, ça devient beaucoup plus balèze avec sed, voir
http://sed.sourceforge.net/grabbag/scripts/dc_overview.htm
pour des pistes.


Oui, ça devient balèze avec sed, mais c'est tout à fait possible: sed
est une machine de Turing.


Oui, oui. Si dc a été réécrit en sed, on peut se dire que tout
est possible en sed.

http://sed.sourceforge.net/grabbag/scripts/dc.sed

Voici par exemple, une addition binaire en sed. Le reste est trivial
(conversion binaire/décimal, multiplication, etc).


La conversion en binaire n'est pas forcément la plus appropriée
en sed. Pour des additions/multiplications, on peut se contenter
de remplacer 3124 par dddcbbaaaa par exemple. Une addition est
une juxtaposition, multiplier par 10 se fait par y/abcd/bcde/
À partir de là, facile de faire une multiplication:

echo 123 456 | sed 'h;s/ .*//;:1
# convertie 123 en cbbaaa:
s/$/;9876543210aaaaaaaaaa/
s/([0-9])(.*);.*1.{10}(.*)/32/;/[0-9]/!b2
y/abcdefgh/bcdefghi/;b1
:2

# multiplication:
G;s/n[^ ]*//;:3
s/(.*) .*/&:9181716151413121110/;/ :/b4
s/(.):.*1/:/;H;s/:.*//;y/abcdefgh/bcdefghi/;b3
:4

# reformatage:
g;s/n[^ ]* //g;s/[^a-z]//g;s/$/:kihgfedcba/;:5
s/^(([^:])2*)([^:]*:.*2)/31/;t5
s/://;:6
s/(.)(.)2{10}/112/;t6

# convertion de lettres en chiffres
s/([a-z])1*/&9876543210/g
s/.{10}(.)[0-9]*/1/g;s/^0*(.)/1/
'
par exemple. C'est sur que c'est pas rapide.

dc.sed fait des trucs beaucoup plus sioux. C'est expliqué à
l'URL que je donnais
(http://sed.sourceforge.net/grabbag/scripts/dc_overview.htm).

--
Stéphane


Avatar
David LE BOURGEOIS
Merci pour vos solutions et les liens vers la documentation
enrichissante sur sed.

Je vais pour l'instant rester sur la solution donnée en Perl, car la
simplicité de la réponse rejoint celle de la question. Par contre, pour
les solutions avec sed, cela dépasse mes connaissances sur l'outil.
Je vais donc accélérer ma formation sed, et j'y reviendrais lorsque
j'aurais compris le contenu de arkanoid.sed d' Aurélio Marinho :-).

A bientôt.