sed를 사용하여 URL 줄을 정리하여 도메인 만 추출하려고합니다.
그래서 :
http://www.suepearson.co.uk/product/174/71/3816/
내가 원하는:
http://www.suepearson.co.uk/
(후행 슬래시 유무에 관계없이 중요하지 않습니다)
나는 시도했다 :
sed 's|\(http:\/\/.*?\/\).*|\1|'
(비 욕심 많은 정량자를 피함)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
그러나 나는 탐욕스럽지 않은 수량 자 ( ?
)를 작동시킬 수 없으므로 항상 전체 문자열과 일치하게됩니다.
답변
기본적이거나 확장 된 Posix / GNU 정규식은 욕심없는 정량자를 인식하지 못합니다. 나중에 정규식이 필요합니다. 다행히도이 컨텍스트에 대한 Perl 정규식은 다음과 같이 쉽게 얻을 수 있습니다.
perl -pe 's|(http://.*?/).*|\1|'
답변
이 특정 경우, 욕심없는 정규식을 사용하지 않고도 작업을 수행 할 수 있습니다.
이 욕심없는 정규식 [^/]*
대신 다음을 시도하십시오 .*?
.
sed 's|\(http://[^/]*/\).*|\1|g'
답변
sed를 사용하면 일반적으로 구분 기호까지 구분 기호를 제외한 모든 항목을 검색하여 욕심없는 검색을 구현합니다.
echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'
산출:
http://www.suon.co.uk
이것은:
- 출력하지 않습니다
-n
- 검색, 패턴 일치, 교체 및 인쇄
s/<pattern>/<replace>/p
- 사용하는
;
검색 명령 구분을 대신/
하므로 입력하기 쉽도록하기 위해s;<pattern>;<replace>;p
- 괄호 사이의 일치를 기억하십시오
\(
…\)
, 나중에\1
,\2
… - 시합
http://
- 괄호 안에 아무것도 다음에
[]
,[ab/]
의미 중 하나a
또는b
또는/
- 처음
^
에[]
수단not
, 그래서 아무것도 뒤에 만의 것[]
- 그래서
[^/]
제외하고는 아무것도 의미/
의 문자를 *
이전 그룹을 반복하는 것이므로를[^/]*
제외한 문자를 의미합니다/
.- 지금까지는
sed -n 's;\(http://[^/]*\)
검색하고 기억하고http://
뒤에/
찾은 것을 제외한 모든 문자를 의미합니다. - 우리는 도메인의 끝까지 검색하고 싶기 때문에 다음에 멈추고 끝에
/
다른 것을 추가 하고 싶습니다./
sed -n 's;\(http://[^/]*\)/'
.*
- 이제 그룹 1 (
\1
) 에서 기억 된 일치 는 도메인이므로 일치하는 줄을 그룹에 저장된 내용으로 바꾸고\1
인쇄하십시오.sed -n 's;\(http://[^/]*\)/.*;\1;p'
도메인 뒤에 백 슬래시를 포함 시키려면 그룹에 백 슬래시를 하나 더 추가하여 기억하십시오.
echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'
산출:
http://www.suon.co.uk/
답변
sed는 “욕심없는”연산자를 지원하지 않습니다.
일치에서 “/”를 제외 시키려면 “[]”연산자를 사용해야합니다.
sed 's,\(http://[^/]*\)/.*,\1,'
PS “/”를 백 슬래시 할 필요가 없습니다.
답변
에 게으른 (심지어) 수량화 시뮬레이션 sed
그리고 다른 모든 정규식 맛!
-
식의 첫 항목 찾기 :
-
POSIX ERE (
-r
옵션 사용 )정규식 :
(EXPRESSION).*|.
sed :
sed -r 's/(EXPRESSION).*|./\1/g' # Global `g` modifier should be on
예 (첫 번째 숫자 찾기) 라이브 데모 :
$ sed -r 's/([0-9]+).*|./\1/g' <<< 'foo 12 bar 34'
12
어떻게 작동 합니까?
이 정규 표현식은 교대로부터 이익을 얻는다
|
. 각 위치 엔진에서 그와 함께가는 의미 (이 아니라 다른 엔진의 몇 다음에하는 POSIX 표준입니다) 가장 긴 일치를 선택하려고.
일치가 발견 될 때까지([0-9]+).*
. 그러나 질서도 중요합니다.글로벌 플래그가 설정되었으므로 엔진은 입력 문자열 또는 대상의 끝까지 문자별로 문자를 계속 일치시킵니다. 교대로 왼쪽의 첫 번째 및 유일한 캡처 그룹이 일치
(EXPRESSION)
하자마자 나머지 라인도 즉시 소비됩니다.*
. 우리는 이제 첫 번째 캡처 그룹에서 가치를 유지합니다. -
POSIX BRE
정규식 :
\(\(\(EXPRESSION\).*\)*.\)*
sed :
sed 's/\(\(\(EXPRESSION\).*\)*.\)*/\3/'
예 (첫 번째 일련의 숫자 찾기) :
$ sed 's/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/' <<< 'foo 12 bar 34'
12
이 버전은 ERE 버전과 유사하지만 다른 변경 사항이 없습니다. 그게 다야. 각 단일 위치에서 엔진은 숫자를 일치 시키려고합니다.
그것이 발견되면, 다른 다음 숫자가 소비되고 캡처되고 나머지 줄은 즉시 일치합니다. 그렇지 않으면 더 많거나 0을
*
의미
하기 때문에 두 번째 캡처 그룹을 건너 뛰고\(\([0-9]\{1,\}\).*\)*
점.
하나에 도달 하여 단일 문자와 일치 하며이 프로세스는 계속됩니다.
-
-
구분 된 표현식 의 첫 항목 찾기 :
이 방법은 구분 된 문자열의 첫 항목과 일치합니다. 이것을 문자열 블록이라고 부를 수 있습니다.
sed 's/\(END-DELIMITER-EXPRESSION\).*/\1/; \ s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g'
입력 문자열 :
foobar start block #1 end barfoo start block #2 end
-EDE :
end
-SDE :
start
$ sed 's/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g'
산출:
start block #1 end
첫 번째 정규 표현식
\(end\).*
은 첫 번째 구분 기호를 일치시키고 캡처하며, 마지막 구분 기호 인end
최근 캡처 된 문자로 모든 일치를 대체합니다. 이 단계에서 출력은 다음과 같습니다foobar start block #1 end
.그런 다음
\(\(start.*\)*.\)*
위의 POSIX BRE 버전과 동일한 두 번째 정규식으로 결과가 전달됩니다 . 시작 구분 기호start
가 일치하지 않으면 단일 문자 와 일치하고 그렇지 않으면 시작 구분 기호와 일치하고 캡처하고 나머지 문자와 일치합니다.
질문에 직접 대답
접근법 # 2 (구분 된 표현식)를 사용하여 두 가지 적절한 표현식을 선택해야합니다.
-
EDE :
[^:/]\/
-
SDE :
http:
용법:
$ sed 's/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'
산출:
http://www.suepearson.co.uk/
참고 : 동일한 구분 기호로 작동하지 않습니다.
답변
하나 이상의 캐릭터를위한 욕심없는 해결책
이 스레드는 실제로 오래되었지만 사람들이 여전히 필요하다고 생각합니다. 의 첫 번째 발생까지 모든 것을 죽이고 싶다고 가정 해 봅시다 HELLO
. 당신은 말할 수 없습니다 [^HELLO]
…
따라서 좋은 해결책은 입력에서 예상하지 않은 고유 한 단어를 절약 할 수 있다고 가정하면 두 단계로 구성됩니다 top_sekrit
.
이 경우 다음을 수행 할 수 있습니다.
s/HELLO/top_sekrit/ #will only replace the very first occurrence
s/.*top_sekrit// #kill everything till end of the first HELLO
물론 더 간단한 입력으로 더 작은 단어를 사용하거나 단일 문자를 사용할 수도 있습니다.
HTH!
답변
sed-Christoph Sieghart의 욕심없는 매칭
sed에서 욕심없는 일치를 얻는 트릭은 일치하는 문자를 제외하고 모든 문자를 일치시키는 것입니다. 나도 알다시피, 그러나 그것은 귀중한 시간을 낭비하고 쉘 스크립트는 결국 빠르고 쉬워야합니다. 따라서 다른 사람이 필요할 수있는 경우 :
욕심 매칭
% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar
욕심없는 매칭
% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar