2010-01-16 6 views
10

J'ai une regex et un modèle de remplacement qui ont tous deux été testés dans Notepad ++ sur mes données d'entrée et fonctionnent correctement. Quand je les mets dans une expression sed, cependant, rien ne correspond.Echapper aux chaînes sed correctement

Voici la commande sed:

# SEARCH = ([a-zA-Z0-9.]+) [0-9] (.*) 
# REPLACE = \2 (\1) 

sed -e 's/\([a-zA-Z0-9.]+\) [0-9] \(.*\)/\2 \(\1\)/g' 

Voici un échantillonnage des données:

jdoe 1 Doe, John 
jad 1 Doe, Jane 
smith 2 Smith, Jon 

et la sortie désirée:

Doe, John (jdoe) 
Doe, Jane (jad) 
Smith, Jon (smith) 

j'ai essayé de supprimer et à ajouter échappe à différents caractères dans l'expression sed, mais soit n'obtenir rien de semblable ou quelque chose du genre:

sed: -e expression #1, char 42: invalid reference \2 on `s' command's RHS 

Comment puis-je obtenir cette fuite correctement?

Répondre

17

Je trouve généralement plus facile à utiliser l'option -r car cela signifie que échapper est similaire à celle de la plupart des autres langues:

sed -r 's/([a-zA-Z0-9.]+) [0-9] (.*)/\2 (\1)/g' file1.txt 
+0

Cela a fonctionné à merveille. Merci. –

4

Le signe plus doit être échappé quand ne pas utiliser l'interrupteur -r.

9

Quelques avertissements et ajouts à ce que tout le monde a déjà dit:

  1. L'option -r est une extension GNU pour permettre des expressions régulières étendues. BSD a dérivé l'utilisation de sed -E à la place.
  2. Sed et Grep utilisation Basic Regular Expressions
  3. Awk utilise Extended Regular Expressions
  4. Vous devez être à l'aise avec le POSIX specifications tels que IEEE Std 1003.1 si vous voulez écrire des scripts portables, makefile, etc.

Je recommande la réécriture expression comme

's/\([a-zA-Z0-9.]\{1,\}\) [0-9] \(.*\)/\2 (\1)/g' 

qui devrait faire exactement ce que vous voulez dans tout POSIX conforme sed. Si vous vous en souciez vraiment, envisagez de définir la variable d'environnement POSIXLY_CORRECT.

1
$ sed -e 's/\([a-zA-Z0-9.].*\) [0-9] \(.*\)/\2 \(\1\)/g' file 
Doe, John (jdoe) 
Doe, Jane (jad) 
Smith, Jon (smith) 
2

En utilisant awk est beaucoup plus simple ...:

cat test.txt | awk '{ print $3 " " $4 " " "("$1")" }' 

Sortie:

Doe, John (jdoe) 
Doe, Jane (jad) 
Smith, Jon (smith) 

Voir l'homme awk 1