두 정규식 패턴 사이의 문자열 삭제

두 정규식 패턴 사이의 문자열 삭제

다음 내용이 포함된 파일이 있습니다.

..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp

내가 기대하는 결과는

..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

sed를 사용하여 어떻게 이를 달성할 수 있나요?

동시에 두 그룹을 캡처하는 정규식을 작성할 수 없습니다.

  1. 초기 그룹(....\src) - 모든 라인에서 동일합니다.
  2. 변수 그룹 (abc\abc.cpp) 또는 (xyz\xyz.cpp) 또는 (pqr\pqr.cpp) 또는 (pqr\abc.cpp)

답변1

BSD sed또는 최신 버전의 GNU sed(이전 버전의 경우 -E로 대체 -r):

sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
  • #입력에서 s 와 관련된 모호성을 피하기 위해 의 대체( s) 명령에 대한 구분 기호로 사용됩니다.sed\

  • (.*\\src)처음부터 일치 src하고 일치 항목을 캡처된 그룹 1에 넣습니다.

  • (\\[^\]+\\[^\]+$)\끝까지 두 개의 s가 있는 부분과 일치 하고 캡처된 그룹 2에 배치됩니다. .*앞선 것은 첫 번째와 두 번째 캡처된 그룹 사이의 모든 것과 일치합니다.

  • 교체에서는 캡처된 두 그룹을 사용했습니다.

POSIX 방식:

sed 's#\(.*\\src\).*\(\\[^\]\+\\[^\]\+$\)#\1\2#' file.txt

예:

% cat file.txt
..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp

% sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

답변2

대체 솔루션:

GNU greppaste

grep두 패턴을 추출 .*\\src하거나 (\\[^\]+){2}$별도의 줄에 인쇄합니다. 그런 다음 출력은 다음을 사용하여 결합됩니다.paste

$ grep -oE '.*\\src|(\\[^\]+){2}$' ip.txt | paste -d '' - -
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

와 함께perl

$ perl -pe 's/.*\\src\K.*(?=(\\[^\\]+){2}$)//' ip.txt 
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

여기서 패턴 사이의 텍스트 .*\\src(\\[^\\]+){2}$긍정적인 둘러보기를 사용하여 삭제됩니다.

답변3

데이터가 포함된 파일 만들기

-rwxr-xr-x. 1 sasi   webApp  190 Oct  4 13:42 file.txt

아래 명령을 실행

[sasi@localhost temp]$ sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
[sasi@localhost temp]$
[sasi@localhost temp]$
[sasi@localhost temp]$

답변4

왜 이것을 정규식으로 강타합니까? 경로 병합에는 정규 표현식이 필요하지 않습니다. OS 커널은 경로를 따르기 위해 정규식을 사용하지 않습니다.

Awk에서는 백슬래시를 구분 기호로 사용하고 구성 요소는 필드가 됩니다.

awk 'BEGIN { FS = OFS = "\\" } { print $1, $2, $3, $(NF-1), $NF }'

관련 정보