Làm cách nào tôi có thể trích xuất / phân tích một URL hoàn chỉnh từ một chuỗi bán ngẫu nhiên?


12

Tôi muốn có bash parse / trích xuất một URL đầy đủ (và chỉ url) từ một chuỗi ngắn ngẫu nhiên.

Ví dụ:

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

hoặc là

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

hoặc là

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

hoặc là

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

Tôi đã thử sử dụng cat foo_output | egrep -o "https?://[\w'-\.]*\s"nhưng nó dường như không hoạt động.


Nghe có vẻ đáng sợ, tùy thuộc vào những gì bạn muốn làm với URL được trích xuất ...
vonbrand

Câu trả lời:


24

Bạn đã thử chưa:

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

thay thế?

Lưu ý rằng bất cứ điều gì với một lớp ký tự được coi là nghĩa đen, vì vậy nói [\w]không khớp với một ký tự từ . Hơn nữa, bạn không cần phải thoát một metacharacter regex trong một lớp nhân vật, tức là, nói [\.]không hoàn toàn giống như [.].


2
[^ ]là quá rộng, bạn sẽ muốn loại bỏ khoảng trống khác, (, ), có thể hôn mê, và tất cả các nhân vật mà không được phép vào URL.
Stéphane Chazelas

@StephaneChazelas Bạn nói đúng. Tuy nhiên, tôi giả định rằng URL được đặt trước và theo sau là khoảng trắng trừ khi ở đầu hoặc cuối dòng.
devnull

5

Các URI không phù hợp để kết hợp biểu thức chính quy khi được nhúng trong ngôn ngữ tự nhiên. Tuy nhiên, trạng thái hiện tại của nghệ thuật là Mô hình chính quy tự do, chính xác được cải tiến của John Gruber cho các URL phù hợp . Như hiện được đăng, phiên bản một dòng như sau:

(?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 cũng xuất hiện để duy trì một ý chính ở đây , mặc dù mục blog của anh ta làm tốt hơn rất nhiều việc giải thích kho dữ liệu thử nghiệm của anh ta và những hạn chế của mẫu biểu thức chính quy.

Nếu bạn muốn triển khai biểu thức từ dòng lệnh, bạn có thể thấy mình bị giới hạn bởi công cụ biểu thức chính quy bạn đang sử dụng hoặc bởi các vấn đề trích dẫn shell. Tôi đã tìm thấy một tập lệnh Ruby là lựa chọn tốt nhất, nhưng số dặm của bạn có thể thay đổi.


2
Vui lòng bao gồm regex trong câu trả lời của bạn thay vì liên kết với nó.
terdon

@terdon, regrec đầy đủ là khoảng 60 dòng.
vonbrand

2
@vonbrand Tôi biết, tôi đã thấy nó. Chúng tôi chỉ có xu hướng tránh liên kết với các nguồn lực bên ngoài. Toàn bộ quan điểm của các trang SE là trở thành wiki. Điều gì nếu blog bạn liên kết đến ngoại tuyến? Câu trả lời của bạn sẽ trở nên vô dụng. Dù sao, 60 dòng là không nhiều và nó chỉ là 60 dòng cho khả năng đọc.
terdon

2

Vấn đề với các URL phù hợp là mọi thứ đều có thể có trong một URL:

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

Như bạn thấy, URL (hợp lệ) trên chứa $, ?, #, &, ,, .:. Về cơ bản, điều duy nhất bạn có thể chắc chắn rằng URL không chứa là một khoảng trống. Với ý nghĩ đó, bạn có thể trích xuất các URL của mình với một mẫu đơn giản như:

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

Các \Skhớp với bất kỳ không gian nhân vật trong perl biểu thức thông thường tương thích (PCREs), các -Pkích hoạt PCREs cho grep-olàm cho nó in chỉ phân khúc phù hợp của dòng.


0

Tôi sẽ đi xích nhưng một chút khác nhau. Nếu bạn có một đoạn văn bản như của bạn trong một tệp văn bản có tên là String.txt, bạn có thể làm như sau:

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

Giải trình:

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 

Vì có khả năng url có thể không hoạt động, bạn có thể kiểm tra lỗi bổ sung bằng URL quan tâm của mình. ví dụ: wget -p URL -O /dev/nullnó sẽ in các mã lỗi khá khác nhau trong trường hợp URL không khả dụng, vì vậy bạn có thể thiết lập một vòng lặp để xử lý danh sách các liên kết của mình và đưa ra trạng thái hợp lệ của chúng.

Nếu cuối cùng bạn trích xuất các liên kết từ các tệp html thì có thể có một số rắc rối với sedcác trường hợp đặc biệt. Như đã được đề xuất trong một bài đăng hài hước mà bạn có thể đã thấy - tốt nhất không nên sử dụng regexps mà là một công cụ phân tích cú pháp html. Một trình phân tích cú pháp dễ dàng có sẵn như vậy là trình duyệt chỉ văn bản lynx(có sẵn trên bất kỳ linux nào). Điều này cho phép bạn kết xuất ngay lập tức danh sách tất cả các liên kết trong một tệp và sau đó bạn chỉ cần trích xuất các url bạn muốn với grep.

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

Tuy nhiên, điều này sẽ không hoạt động trên hầu hết các tệp html bị xáo trộn hoặc đoạn văn bản có liên kết.


-1

Chỉ egrep -o 'https?://[^ ")]+'

trong đó sẽ bao gồm url()và "http"


3
Làm thế nào khác với câu trả lời của devnull? Tôi hy vọng bạn nhận ra rằng việc sử dụng egrepbị phản đối.
Anthon

Nếu bạn có một cải tiến so với câu trả lời hiện có, bạn có thể tham khảo lại thông qua liên kết "chia sẻ" bên dưới câu trả lời đó. Xem thêm các trang trợ giúp
Jeff Schaller

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

cách khác, nối thêm lệnh SED để lưu nó vào tệp CSV:

| sed 's/;/<tab>/g' > file.csv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.