4

У меня есть строка с текстом и несколькими URL. Как я могу извлечь один конкретный URL (из домена-спекуляции) с помощью sed? Например, у меня есть это:

Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot

и sed должен вернуть это:http://myURL.net/files/IWANTthis

4 ответа4

6

Могут быть некоторые проблемы с sed в особых случаях. Как было предложено во многих местах (например) - не использовать регулярные выражения, а механизм парсера html. Один такой легко доступный парсер содержится только в текстовом браузере lynx (доступен на любом linux). Затем вы просто извлекаете нужные URL-адреса с помощью grep.

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

Однако это не будет работать с искаженными файлами HTML (не может быть проанализировано должным образом) или текстовыми фрагментами со ссылками. Другим простым способом является цепочка. Если у вас есть текстовый фрагмент, похожий на ваш, в текстовом файле st3.txt, вы можете сделать следующее:

grep http ./st3.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 <
grep IWANTthis           => will take only urls containing your text of interest
sort -u                  => will sort and remove duplicates from your list
1

Вы можете использовать grep с расширенным регулярным выражением (регулярное выражение) для этого:

grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< '<input_string>'

Объяснение каждой части команды и регулярного выражения:

  • grep -Eo: мы вызываем grep с двумя вариантами.
    • -E: включить расширенные регулярные выражения POSIX.
    • -o: печатать только совпадающие части каждой строки (без этой опции grep умолчанию печатает целые строки, содержащие совпадающие части).
  • '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?': Это регулярное выражение, вероятно, немного причудливее, чем то, что вам нужно, поэтому вам следует упростить или удалить части, которые излишне сложны для ваших целей. (Сложность является результатом попытки дать общее решение.)
    • ([-+[цифра , ([-+.[:alnum:]]+://)?: Соответствует схеме URL. ? в конце указывает, что это совпадает либо один раз, либо не совпадает вообще (так что myURL.net совпадает, даже если схема не добавлена). Мы включаем немного необычных персонажей -+. потому что RFC 3986 указывает, что имена «[s] cheme состоят из последовательности символов, начинающихся с буквы и сопровождаемых любой комбинацией букв, цифр, плюс ('+'), точки ('.') или дефиса ('- ') "(ударение мое). Если вы уверены, что http:// всегда будет отображаться перед myURL.net , вы можете заменить эту часть регулярного выражения на простой http:// .
    • ([-[:alnum:]]+.)*: Это соответствует поддоменам. Знак * в конце указывает, что это соответствует нулю или более раз (так, чтобы подбирались подобласти типа a.b. в a.b.myURL.net). Мы включили дефис (-), потому что RFC 1035 определяет, что «[метки поддоменов] должны начинаться с буквы, заканчиваться буквой или цифрой и иметь в качестве внутренних символов только буквы, цифры и дефис » (выделено мной). Если вы уверены, что вам не нужно сопоставлять субдомены, то вы можете удалить эту часть регулярного выражения.
    • myURL.net: Это прямое соответствие для буквенной строки myURL.net .
    • (:[[:digit:]]+)?: Это соответствует любому обозначению порта, если оно включено в URL.
    • (/[[:graph:]]*)?: Это соответствует остальной части URL. [:graph:] соответствует любому видимому символу.
  • <<< '<input_string>': мы передаем grep (который принимает файл) нашу входную строку, используя строку here. (echo '<input_string>' | является распространенной альтернативой.)

Пример:

$ grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< 'Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot'
http://myURL.net/files/IWANTthis

Опять же, приведенное выше регулярное выражение, вероятно, слишком сложное для того, что вам нужно. Вы должны изменить его в соответствии с вашими целями. Может работать что-то простое:

grep -Eo 'http://myURL.net(/[[:graph:]]*)?' <<< '<input_string>'
0

Вы можете проанализировать файл для всех URL с помощью sed а затем grep для вашего соответствия.

sed "s/http/\nhttp/g" your.html | sed -n "s#\(.*\)\(http.*//[a-Z0-9./-]*[^a-Z/]\)\(.*\)#\2#p;" | grep IWANTthis

В первом проходе sed заменяет все http на добавленную новую строку, чтобы облегчить sed во втором проходе, где sed разрывает URL-адреса. Это правило, как правило, работает для меня, но вам может потребоваться настроить его в соответствии с вашими потребностями.

Примечание: вы можете сделать это за один проход, но это будет сложно с загадочными, потенциально трудными для поддержки редко используемых команд sed .

0

Вы можете использовать: sed 's/<br\ *\/>/\n/g' html_file | grep myURL.net

Вывод: http://myURL.net/files/IWANTthis

По сути, я заменяю все символы <br /> символом новой строки и собираю соответствующую строку с помощью grep.

Это не учитывает все возможные (разрешенные html) варианты тега <br> , но обрабатывает их в вашем примере.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .