我有一个字符串,其中包含以下文本之一:
我想提取 name.extension 并且可以处理前5个案例,但我无法弄清楚如何使用单个正则表达式完成所有案例。我尝试的一切都变得太贪婪了。这甚至可能吗?
适用于前5个的正则表达式是:
/filename=["']?(.*)(?=["']?;)/
name.extension位于第一个捕获组中,并且必须允许linux中文件名的任何有效字符。这包括'和'和;在其中。
感谢您的帮助!
答案 0 :(得分:3)
分三个阶段进行。
;
以分隔语句。=
上的键/值对。这是一个基本的例子。
def get_value(line)
# Split into statements
statements = line.split(/\s*;\s*/)
# Extract the value of the 2nd statement
_,value = statements[1].split(/\s*=\s*/)
# Strip the quotes
value.gsub!(/^(['"]?)(.*)\1$/, '\2')
return value
end
有一些无法处理的边缘案例:如果您感兴趣的陈述不是第二个,那该怎么办?但这可以根据需要修复。当它在多个步骤中完成而不是试图将其填充到一个正则表达式中时,更容易改进解析。
例如,这可以正确处理%q[inline; filename="name's.extension"]
和%q[inline; filename="name's.\\"extension\\""]
等嵌入和转义引号。
如果你真的想把它当成一个正则表达式,那么,你要求它。
re = /
\bfilename
\s*=\s*
(?:
(?<quote>['"])(?<value>.*)\k<quote> |
(?<value>[^;]+)
)
/x
return re.match(line)['value']
将扩展的处理分为两种选择:一种带引号,一种带引号。否则filename=name.ext;
将获取分号,我无法找到阻止它的另一种方法,但不会引入新问题。
例如,/\bfilename\s*=\s*(?<quote>['"]?)(?<value>.*?)\k<quote>;?$/
将对测试数据起作用,但如果在%q[inline; filename='name.extension'; foo]
之后的分号后面有任何内容,则会失败。
你问过专家正则表达式的知识。作为正则表达式专家的一部分是知道何时不应该使用正则表达式。这可能应该用语法处理,否则你将不断追逐边缘案例。
答案 1 :(得分:2)
试试这个:
/filename=["']?([^"';]+)/
它应该返回第一个捕获组中的字符串。
[
'inline; filename="name.extension";',
'inline; filename="name.extension"',
"inline; filename='name.extension'",
"inline; filename='name.extension';",
"inline; filename=name.extension;",
"inline; filename=name.extension"
].map { |str| str[/filename=["']?([^"';]+)/, 1] == "name.extension" }
=> [true, true, true, true, true, true]
答案 2 :(得分:1)
保持简单和可维护,不要使用正则表达式:
arr = %q(inline; filename="name.extension";
inline; filename="name.extension"
inline; filename='name.extension';
inline; filename='name.extension'
inline; filename=name.extension;
inline; filename=name.extension).lines.map(&:chomp)
p arr.map{|str| str.delete(%q("';) ).split("=").last}
这使用了ruby灵活的字符串文字语法; %q()技巧在这里使用了2次,提供了单引号和双引号的轻松处理。