Extraiga una subcadena con sed que se detenga en la primera aparición del final

Extraiga una subcadena con sed que se detenga en la primera aparición del final

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 Tcomando 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

información relacionada