Sed regexp 问题,从 ^ 到 " 之间的任何内容匹配

Sed regexp 问题,从 ^ 到 " 之间的任何内容匹配

我已经很长时间没有使用sedregexp 了,所以我有点生疏了。简化一下,我有以下输入作为我想从中提取网址的输入:

href="https://unix.stackexchange.com/"

我使用了 regex101.com 上非常有用的工具来优化我的表达式,以最初删除^和第一个之间的所有内容"

s/^.*="//

然而,这不是我想要的,因为我不想依赖这个=标志。但是,如果我将表达式修改为:

s/^.*"//

它匹配最后一个^和最后一个之间的所有内容"并忽略第一个。

显然,我在这里遗漏了一些令我感到沮丧的东西,但我们将不胜感激地收到任何帮助。

在 arch64 上运行 Ubuntu 21.04。

答案1

你缺少的是.*匹配的贪婪地,消耗尽可能多的字符(包括"直到最后一个字符)。

您可以"使用 排除“之间的任何内容” [^"]*,或者切换到提供非贪婪修饰符的正则表达式引擎,例如 Perl.*?

$ printf '%s\n' 'href="https://unix.stackexchange.com/"' | sed 's/^[^"]*"//'
https://unix.stackexchange.com/"

$ printf '%s\n' 'href="https://unix.stackexchange.com/"' | perl -pe 's/^.*?"//'
https://unix.stackexchange.com/"

OTOH,如果您真正想要的是裸露的 URL,您可以匹配并捕获第一个引用和最后一个引用之间的所有内容,并使用反向引用仅重新替换:

$ printf '%s\n' 'href="https://unix.stackexchange.com/"' | sed 's/^[^"]*"\(.*\)"/\1/'
https://unix.stackexchange.com/

严格来说,初始^[^"]*不再需要是非贪婪的,并且可以^.*在这种情况下替换为,因为正则表达式作为一个整体不能消耗第一个",同时仍然匹配第二个(尽管使其贪婪可能会引入不必要的回溯)。

答案2

cut这就是发明这种工作的目的:

$ cut -d'"' -f2 file
https://unix.stackexchange.com/

答案3

您可以将所有内容匹配到第一的 "和:

sed 's/^[^"]*"//'

这将从行的开头匹配^几个(零个或多个*)字符不是双引号 ( [^"]) 后跟双引号"

答案4

使用gawk

awk '{print gensub(/(^.*")(.*")/, "\\2", "g");}' input

在此命令中,gawk内置gensub()函数使用反向引用()将所有捕获组替换为第二个捕获组\\2

如果我们想删除尾部引号,则命令可以更改为:

awk '{print gensub(/(^.*")(.*)(")/, "\\2", "g");}' input

相关内容