使用和不使用终止字符提取文件名

时间:2017-02-20 22:54:34

标签: ruby regex

我有一个字符串,其中包含以下文本之一:

  1. 联;文件名= “扩展名”;
  2. 联;文件名= “扩展名”
  3. 联;文件名= '名称。扩展名';
  4. 联;文件名= '名称。扩展名'
  5. 联;文件名=。扩展名;
  6. 联;文件名=。扩展名
  7. 我想提取 name.extension 并且可以处理前5个案例,但我无法弄清楚如何使用单个正则表达式完成所有案例。我尝试的一切都变得太贪婪了。这甚至可能吗?

    适用于前5个的正则表达式是:

    /filename=["']?(.*)(?=["']?;)/
    

    name.extension位于第一个捕获组中,并且必须允许linux中文件名的任何有效字符。这包括'和'和;在其中。

    感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

分三个阶段进行。

  1. 拆分;以分隔语句。
  2. 拆分=上的键/值对。
  3. 处理价值的引用。
  4. 这是一个基本的例子。

    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次,提供了单引号和双引号的轻松处理。