Ruby 解析CSS文件以获取包含右或左单词的选择器的单个声明
我需要解析一个CSS文件,以获得在其声明(块)中包含右或左单词的单个选择器。并将选择器及其相应的声明(块)添加到数组或散列中。例如:Ruby 解析CSS文件以获取包含右或左单词的选择器的单个声明,ruby,regex,Ruby,Regex,我需要解析一个CSS文件,以获得在其声明(块)中包含右或左单词的单个选择器。并将选择器及其相应的声明(块)添加到数组或散列中。例如: .selector-one { /* This selector and its declaration will be added */ . . float: right; . . } #selector-two { /* This selector and its declaration will be added */ . . ma
.selector-one { /* This selector and its declaration will be added */
.
.
float: right;
.
.
}
#selector-two { /* This selector and its declaration will be added */
.
.
margin-left: 20%;
.
.
}
我尝试使用扫描方法编写它,如下所示:
content.scan(/.*?\{.*?(right|left).*?\}/)
或
但它们中没有一个起作用
我应该提到:
- 选择器的名称是否包含单词left或right无关紧要,我们只需要检查块
- 选择器的名称可以以
或{
}
- 选择器可以分组,因此我们可以有如下内容:
我不知道ruby,但regexp应该是:
[{]([^}]*(right|left)[^}]*)[}]
根据您的示例使用ungreedy、insensitive和global标志,如果它们没有嵌套
# \.(selector-[^{}]*?)\s*\{([^{}]*:[ ]*(?:right|left)[ ]*;[^{}]*)\}
\.
( selector- [^{}]*? ) # (1), Selector
\s*
\{
( # (2 start), Block
[^{}]*
: [ ]*
(?: right | left )
[ ]* ;
[^{}]*
) # (2 end)
\}
输出:
** Grp 0 - ( pos 0 , len 105 )
.selector-one { /* This block will be added to the array */
.
.
float: right;
.
.
}
** Grp 1 - ( pos 1 , len 12 )
selector-one
** Grp 2 - ( pos 15 , len 89 )
/* This block will be added to the array */
.
.
float: right;
.
.
----------------------
** Grp 0 - ( pos 196 , len 106 )
.selector-three { /* This block will be added to the array */
.
.
float: left;
.
.
}
** Grp 1 - ( pos 197 , len 14 )
selector-three
** Grp 2 - ( pos 213 , len 88 )
/* This block will be added to the array */
.
.
float: left;
.
.
Ruby在这方面很方便:
blocks = DATA.each_line
.slice_before(/^\./)
.map(&:join)
.select{ |block| block[/\b(?:left|right)\b/] }
blocks
# => [".selector-one { /* This block will be added to the array */\n .\n .\nfloat: right;\n .\n .\n}\n\n",
# ".selector-three { /* This block will be added to the array */\n .\n .\nfloat: left;\n .\n .\n}\n"]
__END__
.selector-one { /* This block will be added to the array */
.
.
float: right;
.
.
}
.selector-two { /* This block wont be added to the array */
.
.
.
}
.selector-three { /* This block will be added to the array */
.
.
float: left;
.
.
}
- 迭代文件中的行
- 查看结果数组,并在正则表达式
与以/^\./
开头的行匹配时创建子数组
将每个子数组的内容转换回文本字符串map(&:join)
查找每个字符串的内部,如果select
与单词“left”或“right”匹配,则传递字符串/\b(?:left | right)\b/
/\b(?:left | right)\b/
这样的模式很重要,因为正在搜索的字符串可以嵌入到较长的字符串中,如“leftover”或“bright”,并且您不希望得到假阳性
您可能以前没有见过,但它们对于这样的测试代码非常方便<代码>\uuuu END\uuuu标记脚本的结束,它之后的任何内容都可以被视为伪数据文件,可以通过
数据
访问。因此,考虑从文件中读取的代码。 ,您也可以使用CSS解析器,并扫描.< /p>。
现在开始吐球代码
tree = Crass.parse(css)
nodes_with_right_or_left = tree.select do |node|
node[:children] and node[:children].detect do |child|
child[:value] == "right" or child[:value] == "left"
end
end
YMMV:-)感谢所有回答我问题的人。不幸的是,没有人能解决这个问题。下面是我如何实现它的:
input.scan(/[^{}]*\{[^}]*?(?:\Wright\W|\Wleft\W)[^}]*\}/)
关键是scan方法中的括号构成了一个捕获组。所以,我们需要把它变成一个非捕获组,使用<代码>:
我很抱歉,如果我的问题不清楚,因为我没有考虑其他方法来编写这个程序。我更新了我的问题。
tree = Crass.parse(css)
nodes_with_right_or_left = tree.select do |node|
node[:children] and node[:children].detect do |child|
child[:value] == "right" or child[:value] == "left"
end
end
input.scan(/[^{}]*\{[^}]*?(?:\Wright\W|\Wleft\W)[^}]*\}/)