[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: