Извлечь строку из строки с помощью RegEx в терминале
У меня есть строка , например first url, second url, third url
, и хотелось бы извлечь только url
после слова second
в терминале OS X (только первое вхождение). Как я могу это сделать?
В моем любимом редакторе я использовал regex /second (url)/
и использовал $1
, чтобы извлечь его, я просто не знаю, как это сделать в терминале.
Имейте в виду, что url
является фактическим URL-адресом, я буду использовать одно из этих выражений для его соответствия: Regex для соответствия URL
Ответы
Ответ 1
echo 'first url, second url, third url' | sed 's/.*second//'
Изменить: я неправильно понял. Лучше:
echo 'first url, second url, third url' | sed 's/.*second \([^ ]*\).*/\1/'
или
echo 'first url, second url, third url' | perl -nle 'm/second ([^ ]*)/; print $1'
Ответ 2
В другом ответе вы все еще остаетесь со всем после нужного URL-адреса. Поэтому я предлагаю вам следующее решение.
echo 'first url, second url, third url' | sed 's/.*second \(url\)*.*/\1/'
В sed вы группируете выражение, избегая круглых скобок вокруг него (стандарт POSIX).
Ответ 3
Трубопровод к другому процессу (например, "sed" и "perl", предложенный выше) может быть очень дорогостоящим, особенно если вам нужно выполнить эту операцию несколько раз. Bash поддерживает regexp:
[[ "string" = ~ regex]]
Аналогично тому, как вы извлекаете совпадения в своем любимом редакторе с помощью $1
, $2
и т.д., Bash заполняет массив $BASH_REMATCH
всеми совпадениями.
В вашем конкретном примере:
str="first usr1, second url2, third url3"
if [[ $str =~ (second )([^,]*) ]]; then echo "match: '${BASH_REMATCH[2]}'"; else echo "no match found"; fi
Вывод:
match: 'url2'
В частности, =~
поддерживает расширенные регулярные выражения как определено POSIX, но с расширениями для платформы (которые различаются по степени и могут быть несовместима).
На платформах Linux (GNU userland) см. man grep
; на платформах macOS/BSD, см. man re_format
.
Ответ 4
При попытке этого вы, возможно, забыли, это аргумент -E
для sed
.
От sed --help
:
-E, -r, --regexp-extended
use extended regular expressions in the script
(for portability use POSIX -E).
Вам не нужно значительно менять ваше регулярное выражение, но вам нужно добавить .*
, чтобы он с жадностью совпадал с ним, чтобы удалить другую часть строки.
Это отлично работает для меня:
echo "first url, second url, third url" | sed -E 's/.*second (url).*/\1/'
Вывод:
url
В котором вывод "url" на самом деле является вторым экземпляром в строке. Но если вы уже знаете, что он отформатирован между запятой и пробелом, и вы не разрешаете эти символы в URL-адресах, то регулярное выражение [^,]*
должно быть в порядке.
Необязательно:
echo "first http://test.url/1, second ://test.url/with spaces/2, third ftp://test.url/3" \
| sed -E 's/.*second ([a-zA-Z]*:\/\/[^,]*).*/\1/'
Что правильно выводит:
://example.com/with spaces/2