2010-08-20 2 views
26

У меня есть строку как first url, second url, third url и хотел бы извлечь только url после слова second в OS X Terminal (только первое вхождение). Как мне это сделать?Извлечение строки из строки с использованием регулярных выражений в Терминале

В моего любимого редактора Я использовал регулярные выражения /second (url)/ и использовал $1, чтобы извлечь его, я просто не знаю, как это сделать в терминале.

Имейте в виду, что url является фактическим URL, я буду использовать один из этих выражений, чтобы соответствовать его: Regex to match URL

ответ

41
echo 'first url, second url, third url' | sed 's/.*second//' 

Edit: я не понял. Лучше:

echo 'first url, second url, third url' | sed 's/.*second \([^ ]*\).*/\1/' 

или:

echo 'first url, second url, third url' | perl -nle 'm/second ([^ ]*)/; print $1' 
+0

Это возвращает 'url, third url' =/ –

+0

Третья команда работает лучше всего (нет необходимости скрывать скобки и такой = большой), но она возвращает все вхождения (с моим вводом, длинным файлом, по 13 раз) Мне просто нужен первый –

+0

Я добавил неэлегантный '| sed -n '1 s /\./\./ p'' после команды perl, и все получилось отлично = D Спасибо! –

8

В другом ответе условия, что вы по-прежнему остаетесь со всем после нужного URL. Поэтому я предлагаю вам следующее решение.

echo 'first url, second url, third url' | sed 's/.*second \(url\)*.*/\1/' 

Под sed вы группируете выражение, избегая круглых скобок вокруг него (стандарт POSIX).

+0

+1 для информации об эвакуации =) –

0

При попытке этого, вы, вероятно, забыли аргумент -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 
4

трубопровода к другому процессу (например, 'СЭД' и 'Perl' было предложено выше), может быть очень дорогим, особенно когда вам нужно выполните эту операцию несколько раз.Bash не поддерживает регулярное выражение:

[[ "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' 

В частности, =~ поддерживает расширенный регулярные выражения as defined by POSIX, но с расширений для конкретных платформ (которые различаются по степени и может быть несовместимым).
На платформах Linux (GNU userland), см. man grep; на платформах macOS/BSD, см. man re_format.

Смежные вопросы