非贪婪(不情愿)正则表达式在sed中匹配?

我正在尝试使用sed来清理网址以提取域名..

所以来自:

http://www.suepearson.co.uk/product/174/71/3816/

我想要:

http://www.suepearson.co.uk/

(无论是否有训练斜线,都没关系)

我努力了:

 sed 's|(http://.*?/).*|1|'

和(逃避非贪婪量词)

sed 's|(http://.*?/).*|1|'

但我似乎无法让非贪婪量词工作,所以它总是匹配整个字符串。


基本或扩展的Posix / GNU正则表达式都不识别非贪婪量词; 你需要一个更晚的正则表达式。 幸运的是,这个上下文的Perl正则表达式很容易获得:

perl -pe 's|(http://.*?/).*|1|'

试试[^/]*而不是.*?

sed 's|(http://[^/]*/).*|1|g'

对于sed,我通常通过搜索除分隔符之外的任何内容来实现非贪婪搜索,直到分隔符:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;(http://[^/]*)/.*;1;p'

输出:

http://www.suon.co.uk

这是:

  • 不要输出-n
  • 搜索,匹配模式,替换并打印s/<pattern>/<replace>/p
  • 使用; 搜索命令分隔符而不是/使其更容易输入s;<pattern>;<replace>;p
  • 记住括号( ... )之间的匹配,稍后可以用12 ...进行访问......
  • 匹配http://
  • 之后是括号[]的任何内容, [ab/]表示ab/
  • 第一个^ in []意思not ,所以除了[]的东西之外
  • 所以[^/]意味着除/字符以外的任何内容
  • *是重复上一组,因此[^/]*表示除/之外的字符。
  • 到目前为止, sed -n 's;(http://[^/]*)表示搜索并记住http://后跟除/之外的任何字符,并记住您找到的内容
  • 我们要搜索直到域的末尾,所以停在下一个/所以添加另一个/最后: sed -n 's;(http://[^/]*)/'但我们想匹配域名之后的其余部分如此添加.*
  • 现在在组1( 1 )中记住的比赛是域,因此用组1保存的东西替换匹配的线并且打印: sed -n 's;(http://[^/]*)/.*;1;p'
  • 如果你想在域之后加入反斜杠,那么在组中添加一个反斜杠来记住:

    echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;(http://[^/]*/).*;1;p'
    

    输出:

    http://www.suon.co.uk/
    
    链接地址: http://www.djcxy.com/p/47123.html

    上一篇: Non greedy (reluctant) regex matching in sed?

    下一篇: Environment variable substitution in sed