Yarı rastgele bir dizeden tam bir URL'yi nasıl ayıklayabilir / ayrıştırabilirim?


12

Ben bash ayrıştırmak / rastgele bir kısa dize tam bir URL (ve sadece url) ayıklamak istiyorum.

Örnekler:

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

veya

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

veya

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

veya

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

Kullanmayı denedim cat foo_output | egrep -o "https?://[\w'-\.]*\s"ama işe yaramadı.


Çıkarılan URL ile ne yapmak istediğinize bağlı olarak korkutucu geliyor ...
vonbrand

Yanıtlar:


24

Denedin mi:

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

yerine?

Bir karakter sınıfına sahip herhangi bir şeyin değişmez olarak alındığına dikkat edin, bu nedenle deyim [\w]bir kelime karakteriyle eşleşmez . Dahası, bir karakter sınıfı içinde normal ifade metakarakterinden kaçmanıza gerek yoktur, yani demekle [\.]aynı değildir [.].


2
[^ ]çok geniş, diğer boşlukları hariç tutmak isteyeceksiniz, (, ), muhtemelen komalar ve URL'lerin izin verilmez tüm karakter.
Stéphane Chazelas

@StephaneChazelas Haklısın. Ancak, URL'nin öncesinde ve satırın başında veya sonunda olmadığı sürece bir boşluk olduğunu varsaydım .
devnull

5

URI'ler, doğal dilde gömüldüğünde düzenli ifade eşleşmesi için uygun değildir. Bununla birlikte, mevcut teknik durum John Gruber'in Eşleşen URL'ler için Geliştirilmiş Liberal, Doğru Regex Kalıbıdır . Şu anda yayınlandığı gibi, tek satırlı sürüm aşağıdaki gibidir:

(?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 da burada bir özlüyor gibi görünüyor , ancak blog girişi test grubunu ve normal ifade modelinin sınırlamalarını açıklamaktan çok daha iyi bir iş çıkarıyor.

İfadeyi komut satırından uygulamak istiyorsanız, kendinizi kullandığınız normal ifade motoruyla veya kabuk alıntılama sorunları ile sınırlı bulabilirsiniz. En iyi seçenek olarak bir Ruby betiği buldum, ancak kilometreniz değişebilir.


2
Lütfen cevaba bağlamak yerine cevabınıza normal ifadeyi ekleyin.
terdon

@terdon, tam normal ifade yaklaşık 60 satırdır.
vonbrand

2
@vonbrand biliyorum, gördüm. Sadece dış kaynaklara bağlantı vermekten kaçınırız. SE sitelerinin asıl amacı bir wiki olmaktır. Bağlandığınız blog çevrimdışı olursa ne olur? Cevabınız işe yaramayacak. Her neyse, 60 satır o kadar da değil ve okunabilirlik için sadece 60 satır.
terdon

2

Eşleşen URL'lerle ilgili sorun , bir URL'de hemen hemen her şeyin olabileceğidir:

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

Gördüğünüz gibi, içerdiği (geçerli) Yukarıdaki URL $, ?, #, &, ,, .ve :. Temel olarak, bir URL'nin içermediğinden emin olabileceğiniz tek şey bir boşluktur. Bunu göz önünde bulundurarak, URL'lerinizi aşağıdaki kadar basit bir kalıpla çıkarabilirsiniz:

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

\SHerhangi maçları olmayan uzay , perl uyumlu düzenli ifadeler (PCREs) karakterleri -Piçin PCREs aktive grepve -oo çizginin yalnızca eşleşen segmentini yazdırmak yapar.


0

Zincirleme için gitmek istiyorum ama biraz farklı. Strings.txt adlı bir metin dosyasında sizinki gibi bir metin snippet'iniz varsa, aşağıdakileri yapabilirsiniz:

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

Açıklama:

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'nin çalışmayabilme şansı olduğundan, ilgi URL'nizle ek hata kontrolü yapabilirsiniz. ör wget -p URL -O /dev/null. URL'nin kullanılabilir olmaması durumunda oldukça farklı hata kodları yazdıracağından, bağlantı listenizi işlemek ve geçerlilik durumlarını çıkarmak için bir döngü oluşturabilirsiniz.

Nihayetinde html dosyalarından bağlantıları ayıklarsanız sed, özel durumlarda bazı sorunlar olabilir . Muhtemelen daha önce gördüğünüz komik bir (post) önerildiği gibi - regexps değil bir html ayrıştırıcı motoru kullanmak en iyisi olabilir. Bu tür kolay erişilebilen ayrıştırıcılardan biri yalnızca metin tarayıcısıdır lynx(herhangi bir Linux'ta kullanılabilir). Bu, bir dosyadaki tüm bağlantıların listesini anında dökmenizi sağlar ve daha sonra grep ile istediğiniz URL'leri çıkarırsınız.

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

Ancak bu, çoğu karışık html dosyasında veya bağlantı içeren metin parçacıklarında çalışmaz.


-1

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

içerecek url()ve "http"


3
Bu, devnull'un cevabından nasıl farklı? Umarım kullanımının kullanımdan egrepkaldırıldığını fark edersiniz .
Anthon

Mevcut bir cevaba göre bir iyileşme yaşarsanız, bu cevabın altındaki "paylaş" bağlantısı üzerinden geri dönebilirsiniz. Ayrıca yardım sayfalarına bakın
Jeff Schaller

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

alternatif olarak CSV dosyasına depolamak için SED komutunu ekleyin:

| sed 's/;/<tab>/g' > file.csv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.