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