Pregunta:
Tengo algunos datos como
<td><a href="data1">abc</a> ... <a href="data2">abc</a> ... <a href="data3">abc</a>
(Se referiría a la línea anterior como data
en el código a continuación)
Necesito data1
entre el primer "
y "
así que lo hago
echo 'data' | sed 's/.*"\(.*\)".*/\1/'
pero me devuelve la última cadena entre "
y "
siempre, es decir, en este caso me devolvería data3
en lugar de data1
Para obtener data1
, termino haciendo
echo 'data' | sed 's/.*"\(.*\)".*".*".*".*".*/\1/'
¿Cómo obtengo data1
sin tanta redundancia en sed
Respuesta:
El .*
En el patrón de expresiones regulares es codicioso, coincide con una cadena tan larga como sea posible, por lo que las comillas que coincidan serán las últimas.
Dado que el separador es solo un carácter aquí, podemos usar un grupo de corchetes invertidos para hacer coincidir cualquier cosa que no sea una cita, es decir, [^"]
, y luego lo repite para hacer coincidir una cantidad de caracteres que no son comillas.
$ echo '... "foo" ... "bar" ...' | sed 's/[^"]*"\([^"]*\)".*/\1/'
foo
Otra forma sería simplemente eliminar todo hasta la primera cita, luego eliminar todo a partir de la primera cita (nueva):
$ echo '... "foo" ... "bar" ...' | sed 's/^[^"]*"//; s/".*$//'
foo
En las expresiones regulares de Perl, los especificadores *
y +
se pueden convertir en no codiciosos agregando un signo de interrogación, entonces .*?
haría cualquier cosa, pero la menor cantidad de caracteres / bytes como sea posible.