Bash RexEx:逐行读取文件以拉出捕获组中的每个href

时间:2014-06-28 19:36:37

标签: regex bash

我正在尝试逐行读取文件以提取捕获组中的所有锚标记。

到目前为止,我有:

regex="(<a href=\")([A-Za-z0-9:/._-]+)\".*(<\/a>)"
while read line; do    
    if [[ $line =~ $regex ]]; then
        #echo ${BASH_REMATCH}
        href=${BASH_REMATCH[2]}
        echo $href
    fi
done < file.txt

虽然这几乎可以正常工作,因为我正在根据需要捕获网址,但我遇到的问题是当一行包含两个或多个锚<a>标记时,此时我的正则表达式无效捕获第一个锚标记。

所以,我不知道,必须有一种方法来捕捉所有重复的群体。

示例文本将是:

This paragraph has only one anchor tag, <a href="http://google.com" target="_blank">google</a>, lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 

Some paragraph with a lot of anchor tags, <a href="http://en.wikipedia.org/wiki/Regular_expression" target="_blank">regular expression</a>, lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <a href="http://en.wikipedia.org/wiki/Bash_(Unix_shell)" target="_blank">Bash</a>. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <a href="http://stackoverflow.com/questions/ask" target="_blank">asking</a>, lorem ipsum dolor sit amet <a href="http://en.wikipedia.org" target="_blank">wikipedia</a>

您会发现在上面的文字file.txt上运行我的bash脚本的结果是“:

http://google.com
http://en.wikipedia.org/wiki/Regular_expression

...如果您取消注释行#echo ${BASH_REMATCH},您将看到整个段落匹配,只捕获了第一个锚点。

如何继续捕获段落中的所有锚点模式?

谢谢你的时间!

2 个答案:

答案 0 :(得分:2)

您可以使用while循环捕获所有匹配

regex="<a href=\"([A-Za-z0-9:/._-]+)\"[^<]*<\/a>(.*$)"                                                                                                
while read line; do                                                                                                                                   
    while [[ $line =~ $regex ]]; do                                                                                                                   
        href=${BASH_REMATCH[1]}                                                                                                                       
        line=${BASH_REMATCH[2]}                                                                                                                       
        echo $href                                                                                                                                    
    done                                                                                                                                              
done < file.txt

打印

http://google.com
http://en.wikipedia.org/wiki/Regular_expression
http://stackoverflow.com/questions/ask
http://en.wikipedia.org

答案 1 :(得分:1)

你试过grep -o吗?那只打印比赛。

grep -Po '(?<=<a href=\")([A-Za-z0-9:/._-]+)(?=\".*?<\/a>)' file.txt
  • -P打开perl兼容的正则表达式
  • -o仅返回匹配的模式而非整行
  • (?<=...)积极回顾:匹配此模式前面的位置
  • (?=...)肯定前瞻:匹配此模式后面的位置
  • .*?非贪婪匹配:因此,您不会在第一个开放<a>代码与最后一个结束</a>代码
  • 之间匹配

使用前瞻并向后看你不能匹配周围的模式只需要他们的存在。这使grep -o输出完全符合您的需要。

请注意:这种方法非常不稳定,评论等不明白。如果您需要此工具来处理重要事项,请使用xml / html解析器