ฉันจะแยก / แยกวิเคราะห์ URL ที่สมบูรณ์จากสตริงแบบกึ่งสุ่มได้อย่างไร


12

ฉันต้องการ bash parse / แยก 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 ที่แยก ...
vonbrand

คำตอบ:


24

คุณลอง:

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

แทน?

หมายเหตุสิ่งที่มีตัวละครคลาสจะมาเป็นตัวอักษรเพื่อบอกว่า[\w]ไม่ตรงกับตัวอักษรคำว่า นอกจากนี้คุณไม่จำเป็นที่จะหลบหนี metacharacter regex ภายในชั้นเรียนตัวอักษรเช่นพูดไม่ได้มากเช่นเดียวกับ[\.][.]


2
[^ ]กว้างเกินไปคุณจะต้องการที่จะไม่รวมช่องว่างอื่น ๆ(, )อาจ Comas และทุกตัวอักษรที่ไม่ได้รับอนุญาตใน URL ที่
Stéphane Chazelas

@StephaneChazelas คุณพูดถูก อย่างไรก็ตามฉันคิดว่า URL จะถูกนำหน้าและตามด้วยเว้นวรรคยกเว้นที่จุดเริ่มต้นหรือท้ายบรรทัด
devnull

5

URIs ไม่เหมาะสำหรับการจับคู่นิพจน์ทั่วไปเมื่อฝังในภาษาธรรมชาติ อย่างไรก็ตามสถานะปัจจุบันของศิลปะคือจอห์นกรูเบอร์ปรับปรุงเสรีนิยมแบบ Regex ที่ถูกต้องสำหรับ 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`!()\[\]{};:'".,<>?«»“”‘’]))

จอห์นก็ดูเหมือนจะยังคงมีส่วนสำคัญที่นี่แม้ว่ารายการบล็อกของเขาทำงานได้ดีขึ้นมากในการอธิบายคลังข้อมูลทดสอบและข้อ จำกัด ของรูปแบบการแสดงออกปกติ

หากคุณต้องการใช้นิพจน์จากบรรทัดคำสั่งคุณอาจพบว่าตัวเองถูก จำกัด โดยเอ็นจิ้นนิพจน์ทั่วไปที่คุณใช้หรือโดยการอ้างอิงเชลล์ปัญหา ฉันพบว่าสคริปต์ Ruby เป็นตัวเลือกที่ดีที่สุด แต่ระยะทางของคุณอาจแตกต่างกันไป


2
โปรดรวม regex ในคำตอบของคุณแทนที่จะเชื่อมโยงกับมัน
terdon

@terdon, regexp แบบเต็มคือประมาณ 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ตรงกับที่ไม่ใช่พื้นที่ตัวอักษรในนิพจน์ปกติ Perl เข้ากันได้ (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ในบางกรณี ตามที่ได้รับการแนะนำในเรื่องตลก(โพสต์)ที่คุณอาจเคยเห็นมาแล้ว - มันอาจเป็นการดีที่สุดที่จะไม่ใช้ regexps แต่เป็นเครื่องมือแยกวิเคราะห์ html ตัวแยกวิเคราะห์ที่ใช้งานง่ายอย่างหนึ่งคือเบราว์เซอร์ข้อความเท่านั้นlynx(มีให้ใน linux ใด ๆ ) สิ่งนี้ช่วยให้คุณถ่ายโอนรายการลิงก์ทั้งหมดในไฟล์ได้ทันทีจากนั้นคุณก็แยก URL ที่คุณต้องการด้วย grep

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

อย่างไรก็ตามสิ่งนี้จะไม่ทำงานกับไฟล์ html mangled ส่วนใหญ่หรือตัวอย่างข้อความที่มีลิงก์


-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.