我有一个字符串,如first url, second url, third url
,并且只想在OS X终端中的url
字后面提取second
(仅第一次出现) )。我该怎么办?
在我最喜欢的编辑器中我使用正则表达式/second (url)/
并使用$1
来提取它,我只是不知道如何在终端中执行此操作。
请注意,url
是一个实际的网址,我将使用其中一个表达式来匹配它:Regex to match URL
答案 0 :(得分:52)
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'
答案 1 :(得分:13)
管道到另一个进程(例如上面提到的'和#39; perl'以上建议)可能非常昂贵,尤其是当您需要多次运行此操作时。 Bash确实支持regexp:
与使用$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
。
答案 2 :(得分:7)
在另一个答案中,您仍然可以使用所需的URL后的所有内容。所以我建议您使用以下解决方案。
echo 'first url, second url, third url' | sed 's/.*second \(url\)*.*/\1/'
在sed下,您可以通过转义它周围的括号(POSIX标准)来对表达式进行分组。
答案 3 :(得分:2)
尝试此操作时,您可能忘记的是-E
的{{1}}参数。
来自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/'