반 무작위 문자열에서 완전한 URL을 추출 / 파싱하는 방법은 무엇입니까?


12

bash가 임의의 짧은 문자열에서 전체 URL (및 URL 만)을 구문 분석 / 추출하고 싶습니다.

예 :

bob, the address is http://www.google.com

또는

https://foo.com/category/example.html is up

또는

Error 123 occurred at http://bit.ly/~1223456677878

또는

Stats are up: https://foo1234.net/report.jpg

사용을 시도 cat foo_output | egrep -o "https?://[\w'-\.]*\s"했지만 작동하지 않는 것 같습니다.


추출 된 URL로 무엇을하고 싶은지에 따라 무섭게
들립니다

답변:


24

시도해 보았 니:

egrep -o 'https?://[^ ]+' foo_output

대신?

문자 클래스가있는 모든 문자는 리터럴로 간주되므로 단어 문자[\w] 와 일치하지 않습니다 . 또한 문자 클래스 내에서 정규식 메타 문자를 이스케이프 처리 할 필요 가 없습니다 .[\.][.]


2
[^ ]너무 넓, 다른 공백을 제외 할 수 있습니다, (, ), 아마도 혼수 및 URL에서 허용되지 않은 모든 문자.
Stéphane Chazelas

@StephaneChazelas 당신이 맞아요. 그러나 줄의 처음이나 끝이 아닌 한 URL 앞에 공백이 있다고 가정 합니다.
devnull

5

URI는 자연 언어로 임베드 될 때 정규 표현식 일치에 적합하지 않습니다. 그러나 현재의 최신 상태는 John Gruber의 향상된 URL, 정확한 정규식 패턴 URL 입니다. 현재 게시 된대로 한 줄 버전은 다음과 같습니다.

(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))

John은 또한 블로그 항목이 테스트 코퍼스와 정규 표현식 패턴의 제한 사항을 설명하는 데 훨씬 능숙 하지만 여기서 요점을 유지하는 것으로 보입니다 .

명령 행에서 표현식을 구현하려면 사용중인 정규 표현식 엔진 또는 쉘 인용 문제로 인해 제한을받을 수 있습니다. Ruby 스크립트가 최선의 선택임을 발견했지만 마일리지가 다를 수 있습니다.


2
답변에 연결하는 대신 정규식을 답변에 포함하십시오.
terdon

@ terdon, 전체 정규 표현식은 약 60 줄입니다.
vonbrand

2
@vonbrand 알고 있습니다. 우리는 단지 외부 자원과의 연결을 피하는 경향이 있습니다. SE 사이트의 요점은 위키입니다. 링크 한 블로그가 오프라인 상태가되면 어떻게됩니까? 당신의 대답은 쓸모 없게 될 것입니다. 어쨌든 60 줄은 그다지 많지 않으며 가독성을 위해 60 줄에 불과합니다.
terdon

2

일치하는 URL의 문제점은 거의 모든 것이 URL에있을 수 있다는 것입니다.

https://encrypted.google.com/search?hl=en&q=foo#hl=en&q=foo&tbs=qdr:w,sbd:1

당신이 볼 수 있듯이, 포함 (유효) URL 위 $, ?, #, &, ,, .:. 기본적으로 URL에 포함되지 않은 유일한 것은 공백입니다. 이를 염두에두고 다음과 같이 간단한 패턴으로 URL을 추출 할 수 있습니다.

$ grep -oP 'http.?://\S+' file 
http://www.google.com
https://foo.com/category/example.html
http://bit.ly/~1223456677878
https://foo1234.net/report.jpg

\S어떤 일치 가 아닌 공간 는, 펄 호환 정규 표현식 (PCREs)의 문자를 -P위한 PCREs을 활성화 grep하고는 -o이 라인의 일치 세그먼트를 인쇄 할 수 있습니다.


0

나는 체인에 갈 것이지만 약간 다릅니다. strings.txt라는 텍스트 파일에 텍스트 스 니펫이있는 경우 다음과 같이 할 수 있습니다.

grep http ./strings.txt | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | grep IWANTthis | sort -u

설명:

grep http ./st3.txt      => will catch lines with http from text file
sed 's/http/\nhttp/g'    => will insert newline before each http
grep ^http               => will take only lines starting with http
sed 's/\(^http[^ <]*\)\(.*\)/\1/g'   
                         => will preserve string from ^http until first space or < (the latter in hope if 
grep IWANTthis           => will take only urls containing your text of your interest; you can omit this.
sort -u                  => will sort the list and remove duplicates from it 

URL이 작동하지 않을 수 있으므로 관심있는 URL로 추가 오류 검사를 수행 할 수 있습니다. 예를 들어 wget -p URL -O /dev/null-URL을 사용할 수없는 경우 매우 다른 오류 코드를 인쇄하므로 링크 목록을 처리하고 유효성 상태를 출력하도록 루프를 설정할 수 있습니다.

궁극적으로 html 파일에서 링크를 추출하는 sed경우 특별한 경우에 문제가 발생할 수 있습니다 . 아마도 이미 본 것처럼 웃긴 (포스트) 에서 제안했듯이 정규 표현식을 사용하지 않고 html 파서 엔진을 사용하는 것이 가장 좋습니다. 쉽게 구할 수있는 파서 중 하나는 텍스트 전용 브라우저 lynx(Linux에서 사용 가능)입니다. 이를 통해 파일의 모든 링크 목록을 즉시 덤프 한 다음 grep으로 원하는 URL을 추출 할 수 있습니다.

lynx -dump -listonly myhtmlfile.html | grep IWANTthisString | sort -u

그러나 이것은 대부분의 엉망이 된 html 파일 또는 링크가있는 텍스트 스 니펫에서는 작동하지 않습니다.


-1

다만 egrep -o 'https?://[^ ")]+'

여기에는 url()"http" 가 포함됩니다


3
이것이 devnull의 답변과 어떻게 다릅니 까? 나는 사용 egrep이 더 이상 사용되지 않는다는 것을 알고 있기를 바랍니다 .
Anthon

기존 답변보다 개선 된 사항이 있으면 해당 답변 아래의 "공유"링크를 통해 다시 문의 할 수 있습니다. 도움말 페이지를 참조하십시오
Jeff Schaller

-1
cat text-file.txt | grep -Eo '(https?|ftp|file)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]'

또는 SED 명령을 추가하여 CSV 파일로 저장하십시오.

| sed 's/;/<tab>/g' > file.csv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.