奇怪的sed贪婪的正则表达式行为

时间:2014-11-05 13:14:50

标签: regex sed greedy

我试图理解sed wrt这个正则表达式的行为:
sed -n "s/.*Directory \([^>]*\)>/\1/p" /etc/apache2/sites-enabled/*

此处的目标是列出Apache2中所有已启用虚拟主机的webroot路径。

奇怪的是这个示例命令的结果:
sed -n "s/.*Directory \([^>]*\)>/\1/p" <<< "<Directory /var/www/my_site>"符合预期:/var/www/my_site

sed -n "s/.*Directory \([^>]*\)/\1/p" <<< "<Directory /var/www/my_site>"的结果是:/var/www/my_site>

我知道区别在于>的存在。问题是为什么有必要添加>来获得正确的输出? [^>]*应该能够匹配所有内容并停在>,因此不会在括号中捕获它。

我不明白为什么'&gt;'字符在第一个命令中捕获而不在第二个命令中。 [^>]应排除'&gt;'从捕捉括号......

2 个答案:

答案 0 :(得分:2)

在第一行

中,用group1中的内容替换整个字符串: 所以你得到: 的/ var / WWW / my_site

在第二行中,您替换<Directory......site 注意,而不是整个字符串,结尾>不存在具有相同的捕获组。但结尾>保持不变。所以你在输出中看到它。

另一个例子:

$ sed -n "s/fo*\([^o]*\)/\1/p" <<< "foooooowhatever this ooo will leave behind" 
whatever this ooo will leave behind

在上面的示例中,要替换的目标是:foooooowhatever this替换为whatever this,其他字符串将不受影响。

答案 1 :(得分:1)

第一个命令在搜索词中有>但第二个命令没有。{/ p>

[^>]*匹配匹配>之前的所有(不包括>)因此>保留在您的第二个sed命令中:

sed -n "s/.*Directory \([^>]*\)/\1/p"

另请注意第一个命令:

sed -n "s/.*Directory \([^>]*\)>/\1/p"

\1未捕获>,但您的sed命令正在替代它。