2011-01-22 17 views
5

Así que soy bastante bueno con expresiones regulares, pero estoy teniendo algunos problemas con ellos en Unix. Aquí hay dos cosas que me gustaría saber cómo hacerlo:grep en unix/linux: cómo reemplazar o capturar texto?

1) substituyen todo el texto excepto letras, números y guión bajo

En PHP que me gustaría hacer esto: (funciona muy bien)

 
preg_replace('#[^a-zA-Z0-9_]#','',$text). 

In bash Probé esto (con éxito limitado); Parece que dosis no permite utilizar el conjunto completo de expresiones regulares:

 
text="my #1 example!" 
${text/[^a-zA-Z0-9_]/'') 

he probado con sed, pero todavía parece tener problemas con el conjunto de expresiones regulares completo:

echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]// 

Estoy seguro hay una manera de hacerlo con grep, también, pero estaba rompiendo en varias líneas cuando he intentado:

echo abc\!\@\#\$\%\^\&\*\(222 | grep -Eos '[a-zA-Z0-9\_]+'

Y finalmente también trató de usar expr pero parecía que tenían realmente soporte limitado para la expresión regular extendida ... partes


2) Captura (múltiple) de texto

En PHP tan sólo pudiera hacer algo como esto:

 
preg_match('#(word1).*(word2)#',$text,$matches); 

No estoy seguro de cómo sería posible en * nix ...

+0

Ver también: 'perl' – derobert

Respuesta

14

Parte 1

Usted está casi allí con el sed sólo tiene que añadir el modificador g por lo que la sustitución ocurra a nivel mundial, sin la g, la sustitución ocurrirá una sola vez.

$ echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]//g 
my1example 
$ 

Usted hizo lo mismo error con su reemplazo patrón de golpe demasiado: no hacer sustituciones a nivel mundial:

$ text="my #1 example!" 

# non-global replacement. Only the space is delete. 
$ echo ${text/[^a-zA-Z0-9_]/''} 
my#1 example! 

# global replacement by adding an additional/
$ echo ${text//[^a-zA-Z0-9_]/''} 
my1example 

Parte 2

Captura funciona de la misma en sed como lo hizo en PHP regex: adjuntando el patrón entre paréntesis desencadena capturando:

# swap foo and bar's number using capturing and back reference. 
$ echo 'foo1 bar2' | sed -r 's/foo([0-9]+) bar([0-9]+)/foo\2 bar\1/' 
foo2 bar1 
$ 
1

Como alternativa a la buena respuesta de codaddict usando sed, también puede usar tr para la primera parte de su pregunta.

echo "my #1 _ example!" | tr -d -C '[[:alnum:]_]' 

También he hecho uso de la clase [:alnum:] carácter, sólo para mostrar otra opción.

+0

nota, el': macro: '' características en tr' no son consistentes a través de implementaciones, y puede ser falta por completo. Por ejemplo, 'tr' de busybox carece por completo (o lo hizo, la última vez que lo marqué) –

0

¿Qué quieres decir con que no puedes usar la sintaxis de regex para bash?

$ text="my #1 example!" 
$ echo ${text//[^a-zA-Z0-9_]/} 
my1example 

usted tiene que usar // para más de 1 reemplazo.

para su segunda pregunta, la fiesta 3,2 ++

$ [[ $text =~ "(my).*(example)" ]] 
$ echo ${BASH_REMATCH[1]} 
my 
$ echo ${BASH_REMATCH[2]} 
example 
Cuestiones relacionadas