有和没有终止字符

问题描述:

我将包含以下文本的一个字符串中提取文件名:有和没有终止字符

  1. 直列;文件名=“扩展名”;
  2. inline; filename =“name.extension”
  3. inline;文件名=“名称。扩展名”;
  4. inline; filename ='name.extension'
  5. inline;文件名=。扩展名;
  6. inline;文件名=。扩展名

我想提取。扩展名,可以处理前5个案件,但我想不出怎么做都例单一的正则表达式。我所尝试的一切都变得太贪婪。这甚至有可能吗?

,对于前5个工作正则表达式是:

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

的。扩展名是第一个捕获组,而且必须允许在Linux的文件名的任何有效字符。这包括“和”和;在它

感谢所有帮助

+0

到目前为止,没有任何答案可以识别不平衡的报价,例如之前的单一报价和之后的报价。您是否希望该方法确认报价是否平衡? –

+0

其实,这将是蛋糕上的樱桃:-) – Whyves

+0

在某个时刻,你需要一个语法。 – Schwern

分三个阶段进行。

  1. 拆分为;以分开陈述。
  2. 拆分键/值对=
  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],它将会失败。

你问了专家的正则表达式知识。作为正则表达式专家的一部分是知道你什么时候不应该使用正则表达式。这应该可以用语法来处理,否则你会不断追逐边缘案例。

+0

是的,我可以使用代码解决它,但我真的很好奇,看看有专家正则表达式知识的人可以解决这个问题。如果答案是一个正则表达式不能涵盖所有的情况,那么我会回到编程。我试图用回形针修补一些东西,最简单的事情就是修复正则表达式。 – Whyves

+0

@Whyves我用一个正则表达式编辑过,但正如你可以看到它有点讨厌。如果你的意思是[回形针](https://github.com/thoughtbot/paperclip)我不明白你为什么不能用函数调用替换正则表达式。也许你应该问一个关于你想要补丁的问题。 – Schwern

+0

好的,你的观点很清楚:-)我也相信可读​​性和可维护性。但是,我必须说正则表达式的WOW。至于回形针,这不是一个问题,我会使用一个函数。只是当前处理“content-disposition”头文件时遇到了错误,因为我遇到了一个边缘案例,目前它是用正则表达式处理的,所以最简单的方法就是修复这一行代码。和能量进入这个答案! – Whyves

试试这个:

/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] 
+0

在给定的集合上工作,但在内部引号上失败,例如'%q [inline; filename =“name's.extension”]' – Schwern

+0

这就是为什么它很难(至少对我而言)。我不控制文件名,因此它可以包含单引号或双引号以及分号。这就是为什么我使用积极的向前看,但它不处理案件之一。 – Whyves

!。

保持简单和可维护性,不要使用正则表达式:

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

+0

这将删除任何嵌入的引号,如'inline; filename =“name's.extension”;'或'inline; filename =“name。\”extension \“”;' – Schwern

+0

@Schwern是的,但AFAIK无论如何都是可疑的文件名。 – steenslag

+0

违反[稳健性原则](https://en.wikipedia.org/wiki/Robustness_principle)。由于引号被删除,它甚至可能成为一个安全问题,导致开启一个进程来欺骗一个进程读取不同的文件。 – Schwern