我需要从CSS文件中获取所有的URL(url()
表达式)。例如:
b { background: url(img0) }
b { background: url("img1") }
b { background: url('img2') }
b { background: url( img3 ) }
b { background: url( "img4" ) }
b { background: url( 'img5' ) }
b { background: url (img6) }
b { background: url ("img7") }
b { background: url ('img8') }
{ background: url('noimg0) }
{ background: url(noimg1') }
/*b { background: url(noimg2) }*/
b { color: url(noimg3) }
b { content: 'url(noimg4)' }
@media screen and (max-width: 1280px) { b { background: url(img9) } }
b { background: url(img10) }
我需要获取所有的
img*
URL,但不包括 noimg*
URL(无效的语法或属性或在注释内)。我尝试使用传统的正则表达式。经过一些尝试和错误,我得到了以下代码:
private static IEnumerable<string> ParseUrlsRegex (string source)
{
var reUrls = new Regex(@"(?nx)
url \s* \( \s*
(
(?! ['""] )
(?<Url> [^\)]+ )
(?<! ['""] )
|
(?<Quote> ['""] )
(?<Url> .+? )
\k<Quote>
)
\s* \)");
return reUrls.Matches(source)
.Cast<Match>()
.Select(match => match.Groups["Url"].Value);
}
那是一个疯狂的正则表达式,但它仍然无法正常工作 -- 它匹配了3个无效的 URL(即第2、3和4个)。此外,每个人都会说,使用正则表达式解析复杂语法是错误的。
让我们尝试另一种方法。根据 这个问题,唯一可行的选择是 ExCSS(其他选项要么过于简单,要么已过时)。使用 ExCSS,我得到了以下结果:
private static IEnumerable<string> ParseUrlsExCss (string source)
{
var parser = new StylesheetParser();
parser.Parse(source);
return parser.Stylesheet.RuleSets
.SelectMany(i => i.Declarations)
.SelectMany(i => i.Expression.Terms)
.Where(i => i.Type == TermType.Url)
.Select(i => i.Value);
}
与正则表达式解决方案不同,此解决方案不列出无效的URL。但它没有列出一些有效的URL!即9和10。看起来这是某些CSS语法已知问题,而且没有办法在不从头开始重写整个库的情况下解决。ANTLR重写似乎已经被放弃。
问题:如何从CSS文件中提取所有的URL?(我需要解析任何CSS文件,而不仅仅是上面提供的一个例子。请不要检查“noimg”或假设单行声明。)
注:这不是一个“工具推荐”问题,因为任何解决方案都可以,无论是代码片段、对上述解决方案的修复、库还是其他任何东西;而且我已经清楚地定义了我需要的功能。
p[example="...url(link)..."] { color: red }
。(请参见:CSS规范。)因此,您不能简单地取出URL - 您必须从头到尾解析CSS文件并正确处理所有带引号的字符串、注释和CSS标记。话虽如此,我相信一个单一的(非平凡的)正则表达式解决方案可以整洁地完成这个任务,但需要使用回调函数。请稍等... - ridgerunner