¡Gracias! ¿Qué pasa si quisiera encontrar todo lo que hay entre "uno es" y "Cadena" en "Aquí hay un es una cadena"? (sed -e 's / one es (. *) Cadena / \ 1 /'?
usuario1190650
55
@ user1190650 Eso funcionaría si quieres ver el "Aquí hay un" también. Puede probarlo: echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'. Si lo que desea es la parte entre "es" y "Cadena", entonces usted necesita para hacer que la expresión regular coincide con toda la línea: sed -e 's/.*one is\(.*\)String.*/\1/'. En sed, s/pattern/replacement/diga "sustituir 'reemplazo' por 'patrón' en cada línea". Solo cambiará cualquier cosa que coincida con el "patrón", por lo que si desea que reemplace toda la línea, debe hacer que el "patrón" coincida con toda la línea.
Brian Campbell el
9
Esto se rompe cuando la entrada esHere is a String Here is a String
Jay D
1
Sería genial ver la solución para un caso: "Aquí hay una cadena de bla bla bla Aquí hay 1 una cadena de bla bla bla Aquí hay 2 una salida de blash blash String" debería recoger solo la primera subcadena entre Aquí y String "
Jay D
1
@JayD sed no admite coincidencias no codiciosas, consulte esta pregunta para conocer algunas alternativas recomendadas.
Brian Campbell
180
GNU grep también puede admitir una mirada hacia adelante y hacia atrás positiva y negativa: para su caso, el comando sería:
echo "Here is a string"| grep -o -P '(?<=Here).*(?=string)'
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*(?=string)'# Greedy match
is a string, and Here is another
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*?(?=string)'# Non-greedy match (Notice the '?' after '*' in .*)
is a
is another
Tenga en cuenta que la -Popción de GNU grep no existe en el grepincluido en * BSD, o los que vienen con cualquier SVR4 (Solaris, etc.). En FreeBSD, puede instalar el devel/pcrepuerto que incluye pcregrep, que admite PCRE (y mirar hacia adelante / atrás). Las versiones anteriores de OSX usaban GNU grep, pero en OSX Mavericks, -Pse deriva de la versión de FreeBSD, que no incluye la opción.
ghoti
1
Hola, ¿cómo extraigo solo contenido distinto?
Durgesh Suthar
44
Esto no funciona porque si la cadena final "cadena" aparece más de una vez, obtendrá la última aparición, no la siguiente .
Buttle Butkus
66
En el caso de Here is a string a string, tanto" is a " y " is a string a "son respuestas válidas (ignorar las comillas), según las necesidades de interrogación. Depende de usted cuál de estos que quieren y luego la respuesta puede ser diferente en consecuencia. De todos modos, para su requerimiento, esto funcionará:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
Tu respuesta es prometedora. Sin embargo, un problema. ¿Cómo puedo extraerlo a la primera cadena vista si hay varias cadenas en la misma línea? Gracias
Mian Asbat Ahmad
@MianAsbatAhmad Desearía hacer que el *cuantificador sea entre Herey Stringno codicioso (o vago). Sin embargo, el tipo de expresión regular utilizada por sed no admite cuantificadores perezosos ( ?inmediatamente después .*) de acuerdo con esta pregunta de Stackoverflow. Por lo general, para implementar un cuantificador diferido, solo se compararía con todo, excepto el token que no deseaba coincidir, pero en este caso, no hay un solo token, sino una cadena completa String.
Desafortunadamente, esto no funciona si la cadena tiene saltos de línea
Witalo Benicio
No se supone que lo haga. .no coincide con los saltos de línea. Si desea hacer coincidir los saltos de línea, puede reemplazarlos .con algo como [\s\s].
¿Por qué este método es tan lento? cuando se elimina una página html grande con este método, tarda unos 10 segundos.
Adam Johns
@ AdamJohns, ¿qué método? ¿El PCRE? PCRE es bastante complejo de analizar, pero 10 segundos parece extremo. Si le preocupa, le recomiendo que haga una pregunta que incluya un código de ejemplo y vea lo que dicen los expertos.
ghoti
Creo que fue muy lento para mí porque contenía una fuente de un archivo html muy grande en una variable. Cuando escribí el contenido en el archivo y luego analicé el archivo, la velocidad aumentó dramáticamente.
Adam Johns
22
A través de GNU awk,
$ echo "Here is a string"| awk -v FS="(Here|string)"'{print $2}'
is a
El parámetro grep with -P( perl-regexp ) admite \K, lo que ayuda a descartar los caracteres coincidentes previamente. En nuestro caso, la cadena previamente emparejada fue Heredescartada del resultado final.
$ echo "Here is a string"| grep -oP 'Here\K.*(?=string)'
is a
$ echo "Here is a string"| grep -oP 'Here\K(?:(?!string).)*'
is a
Si quieres que la salida sea, is aentonces puedes probar lo siguiente,
$ echo "Here is a string"| grep -oP 'Here\s*\K.*(?=\s+string)'
is a
$ echo "Here is a string"| grep -oP 'Here\s*\K(?:(?!\s+string).)*'
is a
Esto no funciona para: echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}', sólo se devuelve is aen lugar de debe ser is a is a@Avinash Raj
Alper
20
Si tiene un archivo largo con muchas ocurrencias de varias líneas, es útil imprimir primero las líneas numéricas:
¡Gracias! Esta es la única solución que funcionó en mi caso (archivo de texto de varias líneas, en lugar de una sola cadena sin saltos de línea). Obviamente, para tenerlo sin numeración de línea, la -nopción catdebe omitirse.
Jeffrey Lebowski
... en cuyo caso catse puede omitir por completo; sedsabe leer un archivo o entrada estándar.
tripleee
9
Esto podría funcionar para usted (GNU sed):
sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file
Esto presenta cada representación de texto entre dos marcadores (en este caso Herey String) en una nueva línea y conserva nuevas líneas dentro del texto.
Todas las soluciones anteriores tienen deficiencias donde la última cadena de búsqueda se repite en otra parte de la cadena. Me pareció mejor escribir una función bash.
function str_str {local str
str="${1#*${2}}"
str="${str%%$3*}"
echo -n "$str"}# test it ...
mystr="this is a string"
str_str "$mystr""this "" string"
$ echo "Here is a String"| sed 's/.*Here//; s/String.*//'
is a
Tambien funciona
$ echo "Here is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
$ echo "Here is a StringHere is a StringHere is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
Esto elimina cadenas en lugar de generar algo intermedio. Intente eliminar "Hola" con "is" en el comando sed y generará "Hola a"
Jonathan
1
Problema. Mis mensajes de Claws Mail almacenados se envuelven de la siguiente manera, y estoy tratando de extraer las líneas de Asunto:
Subject:[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular
link in major cell growth pathway:Findings point to new potential
therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as
a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway
identified [Lysosomal amino acid transporter SLC38A9 signals arginine
sufficiency to mTORC1]]Message-ID:<20171019190902.18741771@VictoriasJourney.com>
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
sed ':a;N;$!ba;s/\n/ /g' corpus/01| grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
lo que da
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
Here is a Here String
? OI Hereby Dub Thee Sir Stringy
?sed
preguntas frecuentes comunes son "¿cómo puedo extraer texto entre líneas particulares"; esto es stackoverflow.com/questions/16643288/…Respuestas:
fuente
echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'
. Si lo que desea es la parte entre "es" y "Cadena", entonces usted necesita para hacer que la expresión regular coincide con toda la línea:sed -e 's/.*one is\(.*\)String.*/\1/'
. En sed,s/pattern/replacement/
diga "sustituir 'reemplazo' por 'patrón' en cada línea". Solo cambiará cualquier cosa que coincida con el "patrón", por lo que si desea que reemplace toda la línea, debe hacer que el "patrón" coincida con toda la línea.Here is a String Here is a String
GNU grep también puede admitir una mirada hacia adelante y hacia atrás positiva y negativa: para su caso, el comando sería:
Si hay múltiples ocurrencias de
Here
ystring
, puede elegir si desea hacer coincidir entre el primeroHere
y el últimostring
o hacerlas coincidir individualmente. En términos de expresiones regulares, se llama coincidencia codiciosa (primer caso) o coincidencia no codiciosa (segundo caso)fuente
-P
opción de GNU grep no existe en elgrep
incluido en * BSD, o los que vienen con cualquier SVR4 (Solaris, etc.). En FreeBSD, puede instalar eldevel/pcre
puerto que incluyepcregrep
, que admite PCRE (y mirar hacia adelante / atrás). Las versiones anteriores de OSX usaban GNU grep, pero en OSX Mavericks,-P
se deriva de la versión de FreeBSD, que no incluye la opción.Here is a string a string
, tanto" is a "
y" is a string a "
son respuestas válidas (ignorar las comillas), según las necesidades de interrogación. Depende de usted cuál de estos que quieren y luego la respuesta puede ser diferente en consecuencia. De todos modos, para su requerimiento, esto funcionará:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
La respuesta aceptada no elimina el texto que podría ser anterior
Here
o posteriorString
. Esta voluntad:La principal diferencia es la adición de
.*
inmediatamente antesHere
y despuésString
.fuente
*
cuantificador sea entreHere
yString
no codicioso (o vago). Sin embargo, el tipo de expresión regular utilizada por sed no admite cuantificadores perezosos (?
inmediatamente después.*
) de acuerdo con esta pregunta de Stackoverflow. Por lo general, para implementar un cuantificador diferido, solo se compararía con todo, excepto el token que no deseaba coincidir, pero en este caso, no hay un solo token, sino una cadena completaString
..
no coincide con los saltos de línea. Si desea hacer coincidir los saltos de línea, puede reemplazarlos.
con algo como[\s\s]
.Puedes quitar cadenas solo en Bash :
Y si tiene un GNU grep que incluye PCRE , puede usar una aserción de ancho cero:
fuente
A través de GNU awk,
El parámetro grep with
-P
( perl-regexp ) admite\K
, lo que ayuda a descartar los caracteres coincidentes previamente. En nuestro caso, la cadena previamente emparejada fueHere
descartada del resultado final.Si quieres que la salida sea,
is a
entonces puedes probar lo siguiente,fuente
echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'
, sólo se devuelveis a
en lugar de debe seris a is a
@Avinash RajSi tiene un archivo largo con muchas ocurrencias de varias líneas, es útil imprimir primero las líneas numéricas:
fuente
-n
opcióncat
debe omitirse.cat
se puede omitir por completo;sed
sabe leer un archivo o entrada estándar.Esto podría funcionar para usted (GNU sed):
Esto presenta cada representación de texto entre dos marcadores (en este caso
Here
yString
) en una nueva línea y conserva nuevas líneas dentro del texto.fuente
Todas las soluciones anteriores tienen deficiencias donde la última cadena de búsqueda se repite en otra parte de la cadena. Me pareció mejor escribir una función bash.
fuente
Puedes usar dos comandos s
Tambien funciona
fuente
Para entender el
sed
comando, tenemos que construirlo paso a paso.Aquí está tu texto original
Intentemos eliminar
Here
cadena con las
opción de ubicación ensed
En este punto, creo que sería capaz de eliminar
String
, asíPero esta no es su salida deseada.
Para combinar dos comandos sed, use
-e
opciónEspero que esto ayude
fuente
Puede usar
\1
(consulte http://www.grymoire.com/Unix/Sed.html#uh-4 ):El contenido que está dentro de los corchetes se almacenará como
\1
.fuente
Problema. Mis mensajes de Claws Mail almacenados se envuelven de la siguiente manera, y estoy tratando de extraer las líneas de Asunto:
Según A2 en este hilo, ¿Cómo usar sed / grep para extraer texto entre dos palabras? la primera expresión, a continuación, "funciona" siempre que el texto coincidente no contenga una nueva línea:
Sin embargo, a pesar de probar numerosas variantes (
.+?; /s; ...
), no pude hacer que funcionen:Solución 1
Por Extraer texto entre dos cadenas en diferentes líneas
lo que da
Solución 2. *
Per ¿Cómo puedo reemplazar una nueva línea (\ n) usando sed?
reemplazará las nuevas líneas con un espacio.
Encadenando eso con A2 en ¿Cómo usar sed / grep para extraer texto entre dos palabras? , obtenemos:
lo que da
Esta variante elimina los espacios dobles:
dando
fuente