Tengo una cadena de la que necesito extraer una subcadena, pero el final de mi expresión regular se repite. Me gustaría sed para detenerme en la primera instancia del final de mi expresión regular, al igual que las funciones instr() en muchos idiomas devuelven la primera instancia. Ejemplo:
echo "This is a test some stuff I want string junk string end" | sed -n 's/.*\(.te.*ng\).*/\1/p'
returns: test some stuff I want string junk string
I want to return: test some stuff I want string
Respuesta1
grepenfoque (requierePCREapoyo):
s="This is a test some stuff I want string junk string end"
grep -Po 'te.*?ng' <<< $s
Alternativaperlaacercarse:
perl -ne 'print "$&\n" if /te.*?ng/' <<< $s
El resultado (para ambos enfoques):
test some stuff I want string
.*?
-?
aquí estáno codiciosomodificador, indica que coincidamoda minimalista
Respuesta2
Hágalo en dos pasos: primero elimine el prefijo (en caso de que el terminador estuviera presente en el prefijo), luego elimine todo lo que esté después del prefijo. Utilice el T
comando para omitir una línea si no coincide:
echo "This is a test some stuff I want string junk string end" |
sed -n 's/.*\(.te.*ng\)/\1/; T; s/\(ng\).*/\1/p'
Alternativamente, elimine primero las líneas que no coincidan y luego realice el reemplazo cuando lo desee.
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/!d; s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/'
Alternativamente, realice los reemplazos y la impresión final solo en líneas coincidentes.
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/ { s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/p; }'
Respuesta3
Sugeriría usar el comando cortar en su caso.
echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1
Eso cortaría la cuerda en tres partes (antes de la primera, después de la 2. Y entre la 'cadena') con -d"" puedes elegir qué patrón quieres usar como cortador y con -fNumber eliges qué parte llevar. Problema: la 'cadena' se eliminará Solución:
String=`echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1`
String="$(String) string"
echo $String
Agrega la "cadena" delimitadora que se eliminó al final de la variable $String que se definió con la salida.
Respuesta4
# Cómo realizar la coincidencia codiciosa: "test .*? string" usando POSIX sed
sed -e '
/test.*string/!d; # non-interesting line
/^test/s/string/&\
/; # append marker after the first substring "string"
/\n/{P;d;} # initial portion of pattern space is our result
s/test/\
&/;D; # remove portion before the substring "test"
' yourfile
OtroPOSIX-lyEl método consiste en quitar la subcadena "cadena", una a la vez desde el final del espacio del patrón, hasta que solo quede una (después de la subcadena "prueba"). Entonces lo que queda es poner en primer plano la subcadena "prueba":
sed -e '
:loop
s/\(test.*string\).*string.*/\1/
tloop
/^test/!s/test/\
&/;/\n/D
' yourfile