Як я можу витягнути / проаналізувати повну URL-адресу з напів випадкової рядки?


12

Я хотів би проаналізувати / вилучити повну 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]не відповідає слові . Більше того, вам не потрібно уникати метасимволів регулярних виразів в межах класу символів, тобто, кажучи, [\.]це не зовсім так, як [.].


2
[^ ]занадто широкий, ви хочете , щоб виключити інші прогалини, (, ), можливо , коми, і всі символи, які не дозволені в URL.
Стефан Шазелас

@StephaneChazelas Ви маєте рацію. Однак я припускав, що URL-адресі передує і пробіл, якщо тільки на початку чи в кінці рядка.
devnull

5

URI не дуже підходять для регулярного зіставлення виразів, коли вони вбудовані в природну мову. Однак, сучасний стан мистецтва - це вдосконалений ліберальний, точний шаблон регулярного виразів Джона Грубера для відповідності 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
Будь ласка, включіть у свою відповідь регулярну форму замість посилання на неї.
тердон

@terdon, повний регулярний вираз становить приблизно 60 рядків.
фонбранд

2
@vonbrand Я знаю, я це бачив. Ми просто схильні уникати зв’язку із зовнішніми ресурсами. Вся суть сайтів SE - це вікі. Що робити, якщо блог, з яким ви пов’язали, перейде в режим офлайн? Ваша відповідь стане марною. У будь-якому випадку, 60 рядків не так вже й багато, і це лише 60 рядків для читабельності.
тердон

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випадках можуть виникнути проблеми . Як це було запропоновано у смішному (дописі), яке ви, напевно, вже бачили - можливо, найкраще використовувати не регулярні вирази, а механізм розбору HTML. Одним з таких легко доступних аналізаторів є текстовий браузер lynx(доступний на будь-якому Linux). Це дозволяє миттєво скинути список усіх посилань у файлі, а потім просто витягнути потрібні URL-адреси з grep.

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

Однак це не спрацює з більшістю забруднених HTML-файлів або текстових фрагментів із посиланнями.


-1

Просто egrep -o 'https?://[^ ")]+'

який буде включати url()та "http"


3
Чим це відрізняється від відповіді від devnull? Я сподіваюсь, що ви зрозуміли, що використання цього egrepзасобу застаріле.
Антон

Якщо у вас є поліпшення щодо існуючої відповіді, ви можете звернутися до цього посилання за допомогою посилання "поділитися" під цією відповіддю. Дивіться також довідкові сторінки
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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.