Одна команда, берущая две строки для извлечения строки между ними, например «tr» (без выражений)

Одна команда, берущая две строки для извлечения строки между ними, например «tr» (без выражений)

Пилаздесьспособ использования sed для получения текста между двумя другими строками в строке, например:

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

но мне нужна простая команда (вроде tr, но для извлечения строк), которая просто брала бы две строки и обрезала бы все до первой строки или после второй строки, например

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

и будет обрабатывать экранированные символы.

решение1

Если разделители встречаются несколько раз в строках, можно использовать Perl, например:

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

И тогда, например:

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

Вы также можете использовать его как:

between BEG END file1 file2...

решение2

Выполнение этого в sed в общем случае потребовало бы экранирования символов в регулярном выражении, используемом для поиска подстроки, которую я нашелздесь(примечание: дополнительная информацияздесьесли у вас возникнут проблемы).

Затем я нашел, как передать данные в функциюздесь.

Объединяя все это в функцию, которую я могу использовать в своем коде .bashrc, я получаю следующее (хотя мне не нужно задавать переменные a и b, но так легче читать):

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

как сказал Джозеф Р.,этот ответпоказывает, как использовать grep -oP, чтобы сделать то же самое. Чтобы избежать Perl-совместимого регулярного выражения, я нашелэтот, поэтому, возможно, следующее также сработает:

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

Связанный контент