Re: [SHELL] remplacer un caractère dans une sous-chaine
Sylvain Sauvage, jeudi 20 décembre 2007, 16:04:19 CET
>[…]
> La commande « s » prend une ou deux « adresses » :
> adr1,adr2 s/…/…/…
> Ces adresses indiquent à s le cadre dans lequel il doit
> opérer. Ce sont deux expressions régulières marquant la zone
> de texte (une seule adresse → toute la ligne, deux adresses
> → début et fin de zone).
Bon, je raconte n’importe quoi !
Pour sed, les adresses ne fonctionnent que sur plusieurs
lignes.
>[…]
En revanche, la négation :
> /\([^Dd]...\|[dD]\([^a]..\|a\([^t].\|t[^e]\)\)\)\[/,/\]/y/ /_/
>
> en clair, on teste les quatre caractères avant le crochet :
> — soit ce n’est pas d (ou D) ;
> — soit c’est d (ou D) et,
> — pas suivi d’un a ;
> — suivi d’un a et,
> — pas suivi d’un t ;
> — suivi d’un t mais pas d’un e.
>
> (Merci tous les \ à mettre devant les () et les |…
> Encore heureux que « xxx|yyy » n’a pas besoin d’être écrit
> « (xxx)|(yyy) »…)
>
> Bon, là ça ne teste que [Dd]ate, tu pourras facilement
> généraliser.
… peut toujours servir.
Mais ça devient très lourd à gérer avec sed. Il vaudrait
vraiment passer à un vrai langage (Ruby, Perl…).
Pour me pardonner d’avoir dit une ânerie :
#!/usr/bin/ruby
while ligne = STDIN.gets
crochet = false
until ligne.nil?
case ligne
when /\A[dD]ate\[/
print $&
when /\A\[/
crochet = true
print $&
when /\A\]/
crochet = false
print $&
when /\A /
if crochet
print '_'
else
print ' '
end
when /\A./
print $&
end
ligne = $'
end
print "\n"
end
(on peut faire plus court mais j’ai fait lisible…)
Le principe est de manger la ligne petit bout par petit bout
(le \A indique « début de la chaîne »).
$& contient la correspondance de la regexp
$' contient le reste de la chaîne
--
Sylvain Sauvage
Reply to: