使用终端中的RegEx从字符串中提取字符串

时间:2010-08-20 16:10:20

标签: regex bash grep

我有一个字符串,如first url, second url, third url,并且只想在OS X终端中的url字后面提取second(仅第一次出现) )。我该怎么办?

我最喜欢的编辑器中我使用正则表达式/second (url)/并使用$1来提取它,我只是不知道如何在终端中执行此操作。

请注意,url是一个实际的网址,我将使用其中一个表达式来匹配它:Regex to match URL

4 个答案:

答案 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:

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

答案 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/'