나는 다음을 수행하려고합니다 :
echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
sed -E 's:([^\/]*$).*:\1:'
전체 문자열을 캡처하여 대체할 것이라고 생각했는데 Spotify.app
작동하지 않습니다. 대신 전체 문자열을 돌려받습니다.
그래서 내 정규 표현식이 잘못되었을 수도 있다고 생각하여 테스트하기 위해 다음을 수행했습니다.
echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
sed 's:[^\/]*$:PWA.app:'
하지만 예상되는 결과는 다음과 같습니다 /Users/anon/Applications/Chrome Apps.localized/PWA.app
.
그래서 여기서 내가 뭘 잘못하고 있는지 잘 모르겠습니다. 그룹화할 때 동일한 정규식이 일치하지 않는 이유는 무엇입니까?
답변1
필요한 것보다 더 복잡하게 만들고 있습니다.
sed -e 's:.*/::'
탐욕스러운 정규 표현식이 대신 작동하도록 하세요. .*
곧 문자열 끝을 지나갈 것이지만 하드 슬래시와 일치해야 하므로 정규식 엔진은 역추적을 시작하여 /를 찾고 돌아오는 길에 처음 만나는 /에서 중지합니다 . => 문자열의 마지막 슬래시입니다. 이 지점까지만 제거하고 마지막 슬래시와 문자열 끝 이후의 모든 내용을 암시적으로 그대로 둡니다.
답변2
그것예일치하는 항목을 얻은 다음 돌아서 일치하는 값을 찾은 위치로 다시 바꿉니다. 어떤 것과 도 .*
일치할 수 없습니다.뒤쪽에 $
.
아마도 당신은 sed가 에 대한 모든 것을 탐욕스럽게 소비할 것이기 때문에 Except와 같은 것을 원할 것입니다 s:.*([^/]*$):\1:
.*
. non-greedy 수정자를 사용하여 Perl에서 이 작업을 수행할 수 있습니다.
$ echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
perl -pe 's:.*?([^/]*$):\1:'
Spotify.app
/
sed에서는 0개 이상의 종료 경로 구성 요소를 일치시켜 탐욕스럽지 않은 척할 수 있습니다.
$ echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
sed -E 's:([^/]*/)*(.*)$:\2:'
Spotify.app
그러나 POSIX 인식 셸에서 이 작업을 수행하는 경우 셸 매개변수 확장을 사용하여 가장 긴 경로 일치를 제거하는 것이 더 쉬울 수 있습니다.
$ var="/Users/anon/Applications/Chrome Apps.localized/Spotify.app"
$ echo "${var##*/}"
Spotify.app