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)"
}