我是 shell 脚本的新手。我想使用 curl 发送一个 http 请求,然后使用正则表达式提取一些字符串。例如,如何从 http 响应中提取域名?(示例仅用于学习目的)
#!/bin/bash
name=$(curl google.com | grep "www\..*com")
echo "domain name is"
echo $name
使用bash 正则表达式:
re="http://([^/]+)/"
if [[ $name =~ $re ]]; then echo ${BASH_REMATCH[1]}; fi
编辑- OP 要求解释语法。 正则表达式语法是一个很大的话题,我无法在这里完整地解释,但我会尽量解释得足以理解这个例子。
re="http://([^/]+)/"
这是存储在 bash 变量中的正则表达式,re
即您希望输入字符串匹配的内容,并希望提取一个子字符串。分解它:
http://
只是一个字符串 - 输入字符串必须包含此子字符串才能匹配正则表达式[]
通常使用方括号表示“匹配括号内的任何字符”。所以c[ao]t
会匹配“猫”和“婴儿床”。中的^
字符将其[]
修改为“匹配除方括号内的任何字符。因此在这种情况下[^/]
将匹配除“/”之外的任何字符。+
表示“匹配 1 个或多个前面的子表达式”。因此[^/]+
匹配所有字符集中的 1 个或多个,不包括“/”。()
括号表示您要保存与该子表达式匹配的任何内容以供以后处理。如果您使用的语言支持这一点,它将提供一些机制来检索这些子匹配。对于 bash,它是 BASH_REMATCH 数组。接下来,我们必须根据正则表达式测试输入字符串以查看它是否匹配。我们可以使用 bash 条件来做到这一点:
if [[ $name =~ $re ]]; then
echo ${BASH_REMATCH[1]}
fi
在 bash 中,[[ ]]
指定一个扩展的条件测试,并且可能包含=~
bash 正则表达式运算符。在这种情况下,我们测试输入字符串是否$name
与正则表达式匹配$re
。如果它匹配,那么由于正则表达式的构造,我们可以保证我们会有一个子匹配(来自括号()
),我们可以使用 BASH_REMATCH 数组访问它:
${BASH_REMATCH[0]}
将是正则表达式匹配的整个字符串,即“ http://www.google.com/ ”。()
请注意,您可以在正则表达式中有多个子匹配-BASH_REMATCH
元素将按顺序对应于这些。所以在这种情况下${BASH_REMATCH[1]}
将包含“www.google.com”,我认为这是你想要的字符串。请注意,BASH_REMATCH 数组的内容仅适用于最后一次使用正则表达式=~
运算符。所以如果你继续做更多的正则表达式匹配,你必须每次都从这个数组中保存你需要的内容。
这似乎是一个冗长的描述,但我确实掩盖了正则表达式的几个错综复杂的地方。它们可能非常强大,而且我相信性能不错,但正则表达式语法很复杂。正则表达式的实现也各不相同,因此不同的语言将支持不同的功能,并且可能在语法上有细微的差异。特别是在正则表达式中转义字符可能是一个棘手的问题,尤其是当这些字符在给定语言中具有不同的含义时。
请注意$re
,您可以将正则表达式直接放入条件中,而不是将变量设置在单独的行中并在条件中引用此变量。然而,在bash 3.2中,关于是否需要围绕此类文字正则表达式的引号的规则发生了变化。将正则表达式放在单独的变量中是解决此问题的一种直接方法,以便条件在支持=~
匹配运算符的所有 bash 版本中按预期工作。
一种方法是使用sed
. 例如:
echo $name | sed -e 's?http://www\.??'
通常,sed
正则表达式由“/”分隔,但您可以使用“?” 因为您正在搜索“/”。这是另一个 bash 技巧。@DigitalTrauma 的回答提醒我应该提出建议。这是相似的:
echo ${name#http://www.}
(DigitalTrauma 还提醒我需要处理“http://”。)