2015-10-21 111 views
1

我有一個字符串像正則表達式來檢測模式雙引號外面

FIND files where file2=29 AND file32="12" OR file623134="file23" 

本文由用戶輸入的搜索他/她的數據。這由應用程序轉換爲SQL查詢。

例如:FIND替換由SELECT和字符串圖案file[number](實施例:file2file32file623134,如圖串的上方。)變換等FILE_ID=[number] AND FILE_VALUE=[value of FILE[number]。得到的SQL查詢將是:

SELECT * FROM [FILES] WHERE (FILE_ID=2 AND FILE_VALUE=29) AND (FILE_ID=32 AND FILE_VALUE="12") OR (FILE_ID=623134 AND FILEVALUE="file23") 

我實現,到目前爲止,與其他SO問題的幫助,是檢測使用下面的正則表達式的雙引號外的字符串:

(?<![\S"])([^"\s]+)(?![\S"]) 

它的正常工作。但是由於缺乏對正則表達式的瞭解,我無法在此正則表達式中找到可放置file[0-9]模式的位置。請告訴我,我該如何實現這一目標?

如果可能的話,請告訴我如何從這些模式中提取數值,並將其替換爲file123=2(FILE_ID=123 AND FILE_VALUE=2)之間的對應值。

+0

如果我理解你的權利,你想捕捉背後「文件」和值的數字。請試試這個:[Regex101](https://regex101.com/r/aH3wZ4/2) – benjamin

+0

你想在C#或JavaScript中解決這個問題嗎? –

+0

@ NigelThorne C#是首選,所以我可以在服務器端轉換它。但是如果有人在JavaScript中有解決方案,那麼它也是可以接受的。 –

回答

2

這裏是另一個兩步驟approac H:

  • 獲取與他們的ID的鍵值對,並使用背refrences
  • 替換另一個字面"SELECT * FROM [FILES] WHERE"開始部分(文字"FIND files where")取代。

C# demo

var str = "FIND files where file2=29 AND file32=\"12\" OR file623134=\"file23\""; 
var rx = new Regex(@"\bfile(\d+)=""?(\w+)""?"); 
var result = rx.Replace(str, "(FILE_ID=$1 AND FILE_VALUE=$2)") 
       .Replace("FIND files where", "SELECT * FROM [FILES] WHERE"); 
Console.WriteLine(result); 

結果:

SELECT * FROM [FILES] WHERE (FILE_ID=2 AND FILE_VALUE=29) AND (FILE_ID=32 AND FILE_VALUE=12) OR (FILE_ID=623134 AND FILE_VALUE=file23)

正則表達式擊穿:

  • \bfile - 字面file字面即之前沒有與字字符
  • (\d+) - 字面=
  • "? - - 1或0雙引號
  • (\w+) - 被捕獲到組1
  • = 1個或多個字組成的第二捕獲組1個或多個字母數字符號(字母,數字或下劃線)
  • "? - 1或0雙引號
+2

我很喜歡這個。它不擔心格式將是有效的,這可能會讓你打開SQL攻擊..但所有的答案可能會有這個問題。在這種情況下,字符串匹配不能確保字符串被關閉,或者處理字符串中的空格或字符串中的轉義字符。雖然很好,但很簡單。 –

+0

非常感謝。我在所有條件下進行了測試,結果很有效。但是如果你或你@NigelThorne可以解決有關SQL攻擊的問題。我刪除了'SELECT'語句,現在只轉換條件,因爲'SELECT'語句是常量。我還發現了一種在傳遞值時使用參數以避免SQL注入的方法。但客戶端仍然可以在生成的語句中輸入SQL語句。你能告訴我一個正則表達式,它可以檢測像SELECT,UPDATE,INSERT,DELETE,DROP和其他雙引號之外的SQL子句嗎?否則,我確定我會弄明白。 :) –

+1

檢查[這個正則表達式](https://regex101.com/r/xM1dX3/1)。 –

1

您可以檢測你的文件字符串:

file([0-9]+)=\"([0-9]+)\"

此正則表達式返回字符串3,整場比賽,第一個數字和字符串中的第二個數字。

我希望這是你的期望。

我想你好想在使用正則表達式的一個觀點:

各地的多個令牌將括號將它們組合在一起。然後,您可以將量詞應用於該組。例如。設定值)?匹配Set或SetValue。

括號創建一個捕獲組。上面的例子有一個組。比賽結束後,如果Set匹配,則組號1不包含任何內容。如果SetValue匹配,它包含Value。如何訪問該組的內容取決於您使用的軟件或編程語言。零組總是包含整個正則表達式匹配。

來自:http://www.regular-expressions.info/quickstart.html

所以,你必須定義整條生產線正則表達式和每個子串要提取創建匹配組。

+0

感謝@ baddger964的快速入門指南。 :) –

1

這樣

<div id="date">file23="125"</div> 

JS

var data =$('#date').text(); 
var arr = data.split('='); 
var val1 =arr[0]; 
val1 = val1.replace(/[0-9]/g,''); 
var val2 =arr[0]; 
val2 = val2.replace(/[a-zA-Z]/g,''); 
var val = arr[1]; 
val = val.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,''); 
$("#date").html("<span>"+val1 + "</span></br>" + "<span> id="+val2 + "</span></br>" + "<span> value="+val + "</span></br>");  

輸出

file 
id=23 
value=125 

jsfiddle click here

1

比方說我們正在匹配FIND files where file2=29 AND file32="12" OR file623134="file23"

作爲解釋,我會一步步做到這一點。

很明顯,一個正則匹配字符串的正則表達式會匹配。

FIND files where file2=29 AND file32="12" OR file623134="file23" 

FIND files where file2=29 AND file32="12" OR file623134="file23"

首先讓我們決定想從中讀取...並讓他們accessable什麼位。

FIND (files) where file(2)=(29) AND file(32)=("12") OR file(623134)=("file23") 

FIND (files) where file(2)=(29) AND file(32)=("12") OR file(623134)=("file23")

在這裏,我們堅持圍繞所有我們想要讀出位支架。這將這些位定義爲「捕獲組」。在C#中,我們可以給他們一些名字。我們稍後會做。

現在...讓我們推廣這個正則表達式,以便它匹配更多的例子..關鍵是數字,所以我們可以用[0-9]+來捕獲它們。這意味着match a character in the range 0 to 9, at least once

FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("12") OR file([0-9]+)=("file23") 

FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("12") OR file([0-9]+)=("file23")

好了..現在的價值觀......這裏的一些都是字符串..讓匹配...

一個字符串的東西,是不是"通過「包圍」的或"[^"]+" (注..正意味着,我們需要至少一個角色,我們不能匹配空字符串。一個*將讓你匹配空字符串。)

FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+") 

FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+")

一個在本例中的值是一個數..所以讓假定它們可以intergers。

FIND (files) where file([0-9]+)=([0-9]+) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+") 

FIND (files) where file([0-9]+)=([0-9]+) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+")

沒有讓第一個例子特別..所以讓我們假設所有的值可以是字符串或整數。要做出兩個選擇,我們使用|選項匹配器。 (現在..我想你在畫面上大喊「不,他們可以是任何東西......不只是字符串和數字」,但沒關係,我會處理的,後來過。)

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) AND file([0-9]+)=("[^"]+"|[0-9]+) OR file([0-9]+)=("[^"]+"|[0-9]+) 

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) AND file([0-9]+)=("[^"]+"|[0-9]+) OR file([0-9]+)=("[^"]+"|[0-9]+)

現在...我們在這裏有一個相當重複的...最後的部分是相同的,除了一個有「或」,另一個有「與」。這是重要的..我們想知道什麼operator正在使用...所以我們也捕獲。

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) (AND) file([0-9]+)=("[^"]+"|[0-9]+) (OR) file([0-9]+)=("[^"]+"|[0-9]+) 

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) (AND) file([0-9]+)=("[^"]+"|[0-9]+) (OR) file([0-9]+)=("[^"]+"|[0-9]+)

現在我們可以通過移除的最後一部分,並說這是以前的鍵/值對的重複係數進行重複。

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+)((AND|OR) file([0-9]+)=("[^"]+"|[0-9]+))* 

FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+)((AND|OR) file([0-9]+)=("[^"]+"|[0-9]+))*

我添加了一個「*」作爲表達的是最後一部分可以根據需要重複,或不存在一樣多次。

現在...如果我們想要處理的值是任何東西,浮動,時間等,我們需要包括每個匹配或一般的「任何」匹配器。兩者都有缺點。如果我們明確地匹配所有類型,我們就有更多的工作要做。如果我們不這樣做,那麼我們就需要對「如何知道價值何時完成?」做出一些假設。

假設我們假設值後有空格。然後我們就可以匹配所有的字符,直到我們打空白... [^\s]+

FIND (files) where file([0-9]+)=([^\s]+)((AND|OR) file([0-9]+)=([^\s]+))* 

FIND (files) where file([0-9]+)=([^\s]+)((AND|OR) file([0-9]+)=([^\s]+))*

但現在..如果該值是一個字符串,並且它包含它打破的空白。 我們可能想單獨處理字符串來解決這個問題。

FIND (files) where file([0-9]+)=("[^"]+"|[^\s]+)((AND|OR) file([0-9]+)=("[^"]+"|[^\s]+))* 

FIND (files) where file([0-9]+)=("[^"]+"|[^\s]+)((AND|OR) file([0-9]+)=("[^"]+"|[^\s]+))*

"[^"]+"不處理你的字符串中的轉義字符。一個更好的匹配器是"(\\"|[^"])+"其中說的是報價,然後反覆報價或不報價,然後報價。使用這將爲您的表達式添加一個新的捕獲組。我們並不需要這樣做,所以我們可以告訴它不要通過在括號內添加?:來捕獲該組。例如"(?:\\"|[^"])+"

FIND (files) where file([0-9]+)=("(?:\\"|[^"])+"|[^\s]+)((AND|OR) file([0-9]+)=("(?:\\"|[^"])+"|[^\s]+))* 

FIND (files) where file([0-9]+)=("(?:\"|[^"])+"|[^\s]+)((AND|OR) file([0-9]+)=("(?:\"|[^"])+"|[^\s]+))*

正如我提到的。在C#中,你可以命名捕捉組。您通過在組內添加?<name>來完成此操作。

FIND (?<table>files) where file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+)((?<operator>AND|OR) file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+))* 

該表達式中仍然存在重複..但是如果我們將它取出,我們將允許無效表達式匹配。例如。

FIND (?<table>files)((?<operator>AND|OR|where) file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+))+ 

這將使FIND files AND file2="test"匹配..這是不是真的要你想要的,但可能不夠好。

我可能只是使用字符串連接刪除重複,

var pair = @"(?<pair>file(?<key>[0-9]+)=(?<value>"(?:\\\"|[^\"])+\"|[^\s]+))"; 
var query = @"FIND (?<table>files) where "+pair+"((?<operator>AND|OR) "+pair+")*"; 
var ex = new Regex(query); 

或只是把代碼檢查確保第一運營商「其中」 FIND (files)((AND|OR|where) file([0-9]+)=("(?:\\"|[^\"])+\"|[^\s]+))+

var query = @"FIND (?<table>files)(?<condition> (?<operator>AND|OR|where) file(?<key>[0-9]+)=(?<value>"(?:\\\"|[^\"])+\"|[^\s]+))+"; 
var ex = new Regex(query); 
var match = ex.Match(...); 
... match.Groups["table"].Value ... 

你可以現在匹配一個字符串,循環雖然「條件」組,並要求他們的operator,, and值`。

看到How do I access named capturing groups in a .NET Regex?

+0

感謝@Nigel爲這個過程的真棒細分。 :) –

相關問題