2017-02-20 58 views
3

我將包含以下文本的一個字符串中提取文件名:有和沒有終止字符

  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

回答

3

分三個階段進行。

  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

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

在給定的集合上工作,但在內部引號上失敗,例如'%q [inline; filename =「name's.extension」]' – Schwern

+0

這就是爲什麼它很難(至少對我而言)。我不控制文件名,因此它可以包含單引號或雙引號以及分號。這就是爲什麼我使用積極的向前看,但它不處理案件之一。 – Whyves

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次,爲單引號和雙引號提供了無憂的處理。

+0

這將刪除任何嵌入的引號,如'inline; filename =「name's.extension」;'或'inline; filename =「name。\」extension \「」;' – Schwern

+0

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

+0

違反[穩健性原則](https://en.wikipedia.org/wiki/Robustness_principle)。由於引號被刪除,它甚至可能成爲一個安全問題,導致開啓一個進程來欺騙一個進程讀取不同的文件。 – Schwern