Estoy tratando de usar sed para limpiar líneas de URL para extraer solo el dominio.
Entonces de:
http://www.suepearson.co.uk/product/174/71/3816/
Quiero:
http://www.suepearson.co.uk/
(ya sea con o sin la barra inclinada, no importa)
Yo he tratado:
sed 's|\(http:\/\/.*?\/\).*|\1|'
y (escapando del cuantificador no codicioso)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
pero parece que no puedo hacer que el cuantificador no codicioso ( ?
) funcione, por lo que siempre termina haciendo coincidir toda la cadena.
sed -E 's...
. Aún así, no hay un operador reacio.cut -d'/' -f1-3
funciona de manera simple .Respuestas:
Ni la expresión regular Posix / GNU básica ni extendida reconoce el cuantificador no codicioso; Necesitas una expresión regular posterior. Afortunadamente, la expresión regular de Perl para este contexto es bastante fácil de obtener:
fuente
-pi -e
.perl
se requiere por POSIXsed
, usando una sintaxis básicamente idéntica a la delsed
En este caso específico, puede hacer el trabajo sin usar una expresión regular no codiciosa.
Pruebe esta expresión regular no codiciosa en
[^/]*
lugar de.*?
:fuente
([^&=#]+)=([^&#]*)
. Hay casos que no funcionan de esta manera con seguridad, por ejemplo, cuando se analiza el URL para su parte de host y el nombre de ruta con la barra oblicua final, se supone opcional que se excluya de la captura:^(http:\/\/.+?)/?$
Con sed, generalmente implemento la búsqueda no codiciosa buscando cualquier cosa excepto el separador hasta el separador:
Salida:
esto es:
-n
s/<pattern>/<replace>/p
;
separador de comando de búsqueda en lugar de/
hacerlo más fácil para escribirs;<pattern>;<replace>;p
\(
...\)
, luego accesible con\1
,\2
...http://
[]
,[ab/]
significaríaa
ob
o/
^
en los[]
mediosnot
, seguido por cualquier cosa menos la cosa en el[]
[^/]
significa otra cosa que/
el carácter*
es repetir el grupo anterior, entonces[^/]*
significa caracteres excepto/
.sed -n 's;\(http://[^/]*\)
significa buscar y recordarhttp://
seguido de cualquier carácter excepto/
y recordar lo que has encontrado/
agregue otro/
al final:sed -n 's;\(http://[^/]*\)/'
pero queremos hacer coincidir el resto de la línea después del dominio, así que agregue.*
\1
) es el dominio, así que reemplace la línea coincidente con cosas guardadas en el grupo\1
e imprima:sed -n 's;\(http://[^/]*\)/.*;\1;p'
Si también desea incluir una barra diagonal inversa después del dominio, agregue una barra diagonal inversa más en el grupo para recordar:
salida:
fuente
sed no es compatible con el operador "no codicioso".
Debe utilizar el operador "[]" para excluir "/" de la coincidencia.
PD: no hay necesidad de barra diagonal inversa "/".
fuente
s/([[:digit:]]\.[[1-9]]*)0*/\1/
obviamente no funcionaría bien para1.20300
. Sin embargo, dado que la pregunta original era sobre las URL, deberían mencionarse en la respuesta aceptada.Simulación de cuantificador perezoso (no codicioso) en
sed
¡Y todos los demás sabores regex!
Encontrar la primera aparición de una expresión:
POSIX ERE (usando la
-r
opción)Regex:
Sed:
Ejemplo (encontrar la primera secuencia de dígitos) Demostración en vivo :
¿Cómo funciona ?
Esta expresión regular se beneficia de una alternancia
|
. En cada posición, el motor intenta elegir la coincidencia más larga (este es un estándar POSIX que es seguido por un par de otros motores también), lo que significa que continúa.
hasta que se encuentre una coincidencia([0-9]+).*
. Pero el orden también es importante.Como se establece el indicador global, el motor intenta continuar haciendo coincidir carácter por carácter hasta el final de la cadena de entrada o nuestro objetivo. Tan pronto como se empareja el primer y único grupo de captura del lado izquierdo de la alternancia, el
(EXPRESSION)
resto de la línea también se consume de inmediato.*
. Ahora mantenemos nuestro valor en el primer grupo de captura.POSIX BRE
Regex:
Sed:
Ejemplo (encontrar la primera secuencia de dígitos):
Esta es como la versión ERE pero sin alternar. Eso es todo. En cada posición, el motor intenta hacer coincidir un dígito.
Si se encuentra, se consumen y capturan otros dígitos siguientes y el resto de la línea se empareja inmediatamente de lo contrario, ya que
*
significa más o cero se salta sobre el segundo grupo de captura\(\([0-9]\{1,\}\).*\)*
y llega a un punto.
para que coincida con un solo carácter y este proceso continúa.Encontrar la primera aparición de una expresión delimitada :
Este enfoque coincidirá con la primera aparición de una cadena delimitada. Podemos llamarlo un bloque de cuerda.
Cadena de entrada:
-EDE:
end
-SDE:
start
Salida:
First regex
\(end\).*
coincide y captura el delimitador de primer extremoend
y sustituye todos los caracteres coincidentes con caracteres capturados recientemente, que es el delimitador de final. En esta etapa nuestra salida es:foobar start block #1 end
.Luego, el resultado se pasa a la segunda expresión regular
\(\(start.*\)*.\)*
que es la misma que la versión POSIX BRE anterior. Coincide con un solo carácter si el delimitador de iniciostart
no coincide, de lo contrario, coincide y captura el delimitador de inicio y coincide con el resto de caracteres.Responde directamente tu pregunta
Usando el enfoque # 2 (expresión delimitada) debe seleccionar dos expresiones apropiadas:
EDE:
[^:/]\/
SDE:
http:
Uso:
Salida:
Nota: esto no funcionará con delimitadores idénticos.
fuente
sed
y en todos los demás motores que siguen el mismo orden estándar , importa la igualdad. Entoncesecho 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'
no tiene una coincidencia peroecho 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'
sí.Solución no codiciosa para más de un personaje.
Este hilo es muy antiguo pero supongo que la gente todavía lo necesita. Digamos que quieres matar todo hasta la primera aparición de
HELLO
. No puedes decir[^HELLO]
...Entonces, una buena solución implica dos pasos, suponiendo que puede ahorrar una palabra única que no espera en la entrada, digamos
top_sekrit
.En este caso podemos:
Por supuesto, con una entrada más simple, puede usar una palabra más pequeña o incluso un solo carácter.
HTH!
fuente
`
usarlas<$$>
(ya que se$$
expande a su ID de proceso en el shell, aunque tendría que usar comillas dobles en lugar de comillas simples, y eso podría romper otras partes de su expresión regular) o, si está disponible Unicode, algo así<∈∋>
.perl
opython
o algún otro idioma en su lugar.perl
hace esto de una manera menos frágil en una sola línea ...sed - correspondencia no codiciosa por Christoph Sieghart
El truco para obtener una coincidencia no codiciosa en sed es hacer coincidir todos los caracteres, excepto el que termina la coincidencia. Lo sé, es obvio, pero perdí unos minutos preciosos y los scripts de shell deberían ser, después de todo, rápidos y fáciles. Entonces, en caso de que alguien más lo necesite:
Emparejamiento codicioso
Emparejamiento no codicioso
fuente
Esto se puede hacer usando cortar:
fuente
Otra forma, no usar expresiones regulares, es usar el método de campos / delimitador, por ejemplo
fuente
sed
Ciertamente tiene su lugar, pero este no es uno de ellos.Como Dee ha señalado: solo úsalo
cut
. Es mucho más simple y mucho más seguro en este caso. Aquí hay un ejemplo donde extraemos varios componentes de la URL usando la sintaxis Bash:te dio:
Como puede ver, este es un enfoque mucho más flexible.
(todo crédito a Dee)
fuente
fuente
sed -E interpreta las expresiones regulares como expresiones regulares extendidas (modernas)
Actualización: -E en MacOS X, -r en GNU sed.
fuente
-E
es exclusivo de BSDsed
y, por lo tanto, de OS X. Enlaces a páginas de manual.-r
trae expresiones regulares extendidas a GNUsed
como se señala en la corrección de @ stephancheg. Tenga cuidado al usar un comando de variabilidad conocida en las distribuciones 'nix. Aprendí eso por las malas.-r
opción de GNU sed solo cambia las reglas de escape, de acuerdo conAppendix A Extended regular expressions
el archivo de información y algunas pruebas rápidas; en realidad no agrega un calificador no codicioso (GNU sed version 4.2.1
al menos a partir de)-E
como una opción no documentada por un tiempo, pero en la versión 4.2.2.177 , la documentación se actualizó para reflejar eso, por lo que ahora-E
está bien para ambos.Todavía hay esperanza de resolver esto usando sed puro (GNU). A pesar de que esta no es una solución genérica, en algunos casos puede usar "bucles" para eliminar todas las partes innecesarias de la cadena como esta:
El único problema aquí es que también cortará el último carácter separador ('/'), pero si realmente lo necesita, simplemente puede volver a colocarlo después de que finalice el "ciclo", simplemente agregue este comando adicional al final del anterior línea de comando:
fuente
Debido a que declaró específicamente que está tratando de usar sed (en lugar de perl, cut, etc.), intente agrupar. Esto evita que el identificador no codicioso no sea reconocido. El primer grupo es el protocolo (es decir, 'http: //', 'https: //', 'tcp: //', etc.). El segundo grupo es el dominio:
Si no está familiarizado con la agrupación, comience aquí .
fuente
Me doy cuenta de que esta es una entrada antigua, pero alguien puede encontrarla útil. Como el nombre de dominio completo no puede exceder una longitud total de 253 caracteres, reemplace. * Con. \ {1, 255 \}
fuente
Así es como hacer una coincidencia no codiciosa de cadenas de caracteres múltiples usando sed. Digamos que desea cambiar cada
foo...bar
a,<foo...bar>
por ejemplo, esta entrada:debería convertirse en esta salida:
Para hacer eso, convierte foo y bar en caracteres individuales y luego usa la negación de esos caracteres entre ellos:
En lo anterior:
s/@/@A/g; s/{/@B/g; s/}/@C/g
se está convirtiendo{
y}
a cadenas de marcador de posición que no pueden existir en la entrada para que esos caracteres estén disponibles para convertirfoo
ybar
a.s/foo/{/g; s/bar/}/g
es convertirfoo
ybar
a{
y}
respectivamentes/{[^{}]*}/<&>/g
está realizando la operación que queremos: convertirfoo...bar
a<foo...bar>
s/}/bar/g; s/{/foo/g
está convirtiendo{
y de}
vuelta afoo
ybar
.s/@C/}/g; s/@B/{/g; s/@A/@/g
está convirtiendo las cadenas de marcador de posición a sus caracteres originales.Tenga en cuenta que lo anterior no se basa en que ninguna cadena particular no esté presente en la entrada, ya que fabrica tales cadenas en el primer paso, ni le importa qué ocurrencia de una expresión regular particular que desee hacer coincidir, ya que puede usar
{[^{}]*}
tantas veces como sea necesario en la expresión para aislar la coincidencia real que desea y / o con el operador de coincidencia numérica seds, por ejemplo, para reemplazar solo la segunda aparición:fuente
Todavía no he visto esta respuesta, así que así es como puedes hacer esto con
vi
ovim
:Esto ejecuta la
vi
:%s
sustitución globalmente (el finalg
), se abstiene de generar un error si no se encuentra el patrón (e
), luego guarda los cambios resultantes en el disco y se cierra. Esto&>/dev/null
evita que la GUI parpadee brevemente en la pantalla, lo que puede ser molesto.Me gusta usar
vi
a veces por expresiones regulares muy complicado, debido a que (1) Perl esmuertosmoribundos, (2) vim tiene una muy motor de expresiones regulares avanzada, y (3) ya estoy íntimamente familiarizado convi
expresiones regulares en mi edición de uso del día a día documentos.fuente
no te molestes, lo tengo en otro foro :)
fuente
/home/one/two/three/
, si se agrega otro/
como/home/one/two/three/four/myfile.txt
ustedes avidez coincidirfour
así:/home/one/two/three/four
, la pregunta es sobre no expansivosed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1|
funciona tambienfuente
Aquí hay algo que puede hacer con un enfoque de dos pasos y awk:
¡Espero que ayude!
fuente
Otra versión sed:
Coincide
/
seguido de un carácter alfanumérico (por lo que no es otra barra diagonal), así como el resto de los caracteres hasta el final de la línea. Luego lo reemplaza con nada (es decir, lo elimina).fuente
"[[:alnum:]]"
, no"[:alphanum:]"
.