'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에서 일반적으로 이 작업을 수행하려면 내가 찾은 하위 문자열을 찾는 데 사용되는 정규식에서 이스케이프 문자가 필요합니다.여기(참고: 추가 정보여기문제가 발생한 경우).

그런 다음 함수에 파이프하는 방법을 찾았습니다.여기.

이 모든 것을 my 에서 사용할 수 있는 함수로 합치면 .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/"
}

Joseph R.이 언급했듯이,이 답변유사한 작업을 수행하기 위해 grep -oP를 사용하는 방법을 보여줍니다. 내가 찾은 Perl 호환 정규식을 탈출하려면이것, 따라서 다음도 작동할 수 있습니다.

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

관련 정보