shell脚本.如何使用正则表达式提取字符串

ash*_*him 42 regex shell curl

我是shell脚本的新手.我想使用curl发送http请求,然后使用正则表达式提取一些字符串.例如,如何从http响应中提取域名?(该示例仅用于学习目的)

#!/bin/bash
name=$(curl google.com | grep "www\..*com")
echo "domain name is"
echo $name
Run Code Online (Sandbox Code Playgroud)

Dig*_*uma 91

使用bash正则表达式:

re="http://([^/]+)/"
if [[ $name =~ $re ]]; then echo ${BASH_REMATCH[1]}; fi
Run Code Online (Sandbox Code Playgroud)

编辑 - OP要求解释语法. 正则表达式语法是一个很大的主题,我在这里无法完整解释,但我将尝试解释足以理解该示例.

re="http://([^/]+)/"
Run Code Online (Sandbox Code Playgroud)

这是存储在bash变量中的正则表达式,re即您希望输入字符串匹配的内容,并希望提取子字符串.打破它:

  • http:// 只是一个字符串 - 输入字符串必须包含要匹配的正则表达式的子字符串
  • []通常使用方括号,例如"匹配括号内的任何字符".所以c[ao]t会匹配"猫"和"婴儿床".在^该范围内的字符[]修改是这样说的"匹配任何字符,除了那些在方括号内.因此,在这种情况下,[^/]将除了匹配任何字符'/’.
  • 方括号表达式仅匹配一个字符.添加+到它的末尾说"匹配前面的子表达式中的一个或多个".因此[^/]+匹配所有字符集中的一个或多个,不包括"/".
  • ()在子表达式周围加上括号表示您希望保存与子表达式匹配的任何内容,以便以后处理.如果您使用的语言支持此功能,它将提供一些检索这些子匹配的机制.对于bash,它是BASH_REMATCH数组.
  • 最后,我们在"/"上进行完全匹配,以确保我们一直匹配完全限定域名的结尾和以下"/"

接下来,我们必须针对正则表达式测试输入字符串以查看它是否匹配.我们可以使用bash条件来做到这一点:

if [[ $name =~ $re ]]; then
    echo ${BASH_REMATCH[1]}
fi
Run Code Online (Sandbox Code Playgroud)

在bash中,[[ ]]指定扩展条件测试,并且可以包含=~bash正则表达式运算符.在这种情况下,我们测试输入字符串是否$name与正则表达式匹配$re.如果它匹配,那么由于正则表达式的构造,我们保证我们将有一个子匹配(来自括号()),我们可以使用BASH_REMATCH数组访问它:

  • 此数组的元素0 ${BASH_REMATCH[0]}将是正则表达式匹配的整个字符串,即" http://www.google.com/ ".
  • 该数组的后续元素将是子匹配的后续结果.请注意,您可以()在正则表达式中包含多个子匹配- BASH_REMATCH元素将按顺序对应于这些子匹配.所以在这种情况下${BASH_REMATCH[1]}将包含"www.google.com",我认为这是你想要的字符串.

请注意,BASH_REMATCH数组的内容仅适用于上次使用正则表达式=~运算符的情况.因此,如果继续执行更多正则表达式匹配,则必须每次都保存此数组所需的内容.

这似乎是一个冗长的描述,但我真的掩盖了几个复杂的正则表达式.它们可以非常强大,我相信它具有不错的性能,但正则表达式语法很复杂.正则表达式实现也各不相同,因此不同的语言将支持不同的功能,并且可能在语法上有细微差别.特别是在正则表达式中转义字符可能是一个棘手的问题,特别是当这些字符在给定语言中具有不同的含义时.


请注意,不是将$re变量设置在单独的行上并在条件中引用此变量,而是可以将正则表达式直接放入条件中.然而,在bash 3.2中,关于是否需要围绕这些文字正则表达式的引号的规则已经改变.将正则表达式放在单独的变量中是一种简单的方法,因此条件在支持=~匹配运算符的所有bash版本中按预期工作.


Mar*_*ars 7

一种方法是sed.例如:

echo $name | sed -e 's?http://www\.??'
Run Code Online (Sandbox Code Playgroud)

通常,sed正则表达式由`/'分隔,但你可以使用'?' 因为你正在寻找'/'.这是另一个bash技巧.@DigitalTrauma的答案提醒我,我应该提出建议.它类似:

echo ${name#http://www.}
Run Code Online (Sandbox Code Playgroud)

(DigitalTrauma也因为提醒我需要处理"http://"而受到赞誉.)