Comando único que toma dos cadenas para extraer cadenas entre ellas, como 'tr' (sin expresiones)

Comando único que toma dos cadenas para extraer cadenas entre ellas, como 'tr' (sin expresiones)

Sierraaquíuna forma de usar sed para obtener texto entre otras dos cadenas en una línea, como:

sed 's/.*starting_text\(.*\)ending_text.*/\1/'

pero me gustaría un comando simple (como tr, pero para extracción de cadenas) que solo tomara dos cadenas y recortara todo antes de la primera cadena o después de la segunda, por ejemplo

grep something some_file | between message\"\:\" " with"

y se encargaría de los personajes que escapan.

Respuesta1

Si los delimitadores pueden aparecer varias veces por línea, puedes usar perl en su lugar como:

between() {
  perl -Tlne 'BEGIN{$b=shift;$e=shift}
             print for /\Q$b\E(.*?)\Q$e\E/g' "$@"
}

Y luego por ejemplo:

$ echo "[b]test[e] foo [b]bar[e]" | between '[b]' '[e]'
test
bar

También puedes usarlo como:

between BEG END file1 file2...

Respuesta2

Hacer esto en sed genéricamente requeriría caracteres de escape en la expresión regular utilizada para encontrar la subcadena que encontréaquí(nota: más informaciónaquísi tiene problemas).

Luego, encontré cómo canalizar una función.aquí.

Poner todo eso junto en una función que puedo usar en mi .bashrc, parece (aunque no tengo que configurar las variables a y b, pero hace que sea más fácil de leer):

between(){
  a=$(printf '%s\n' "$1"|sed 's![\*.^$/[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![\*.^$/[]!\\&!g')
  sed "s/.*$a\(.*\)$b.*/\1/"
}

como mencionó Joseph R.,esta respuestamuestra cómo usar grep -oP para hacer algo similar. Para escapar de la expresión regular compatible con Perl encontréeste, entonces tal vez lo siguiente también funcione:

between(){
  a=$(printf '%s\n' "$1"|sed 's![]\*.^+?(){|$[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![]\*.^+?(){|$[]!\\&!g')
  grep -oP "(?=$a).*?(?=$b)"
}

información relacionada