2014-06-28 52 views
0

我正在研究一個參數解析器,它將採用參數String[]並將其轉換爲我正在使用的程序可用的輸出。參數用空格分隔,因此在文本here are some arguments中,每個單詞都是一個單獨的參數。但是,我認爲用戶可能需要將單詞分組在一起,因此我在單詞的末尾以反斜槓的形式添加了此功能。另外,由於程序將參數作爲地圖讀取並使用關鍵字來鏈接值(考慮命令行標誌,例如--password 123456,它可以出現在命令的任何位置),因此需要有一種逃避參數的方法,爲了保持一致性,我製作了\<arg>。這意味着刪除反斜槓的正則表達式應忽略字符串開頭的那些表達式。String#replaceAll():在查找表中表示字符串的結尾或開頭?

要考慮的另一件事是能夠用另一個反斜槓來轉義分組反斜槓。這意味着任何反斜槓後面的反斜槓都不應該被刪除。例如,two\\ arguments成爲以two\arguments作爲其元素的陣列。

最後,我想在文字中間留下反斜槓。這意味着正則表達式應該刪除位於字符串末尾或空格後面的反斜槓。

有了這些規則,

  • these\ are\ together將成爲一個爭論與取出反斜槓;
  • back\slash將保持原樣;
  • \test\\會變成\test\;和
  • \test將保持原樣。
我目前使用查找變通,以達到的效果我想

String[] args = input.split("(?<!(?<!\\\\)\\\\) "); 

for (int i = 0; i < args.length; ++i) 
    args[i] = args[i].replaceAll("(?<!\\\\)\\\\(?=)", ""); 

起初,我分裂使用表達式'(?<!(?<!\\)\\) '(不帶引號)的參數,從而以分組的護理。現在解析器繼續剝離反斜槓,這是上述表達式無法處理的任務。

這導致正則表達式(?<!\\)\\(?=)。通常,當該表達在String#replaceAll("(?<!\\\\)\\\\(?=)", "")時,一些有用的效果得以實現:

  • these\ are\ together變得these are together;和
  • back\slash保持原樣。

但是,一旦在字符串的開頭或結尾找到反斜線,該表達式就會變得有問題。例如,\test\\錯誤地被解析爲test\\,因爲第一個反斜槓沒有在另一個反斜槓之前,並且最後一個反斜槓之後沒有空格。經過幾個小時的搜索谷歌使用像regular expression represent empty character,regex ignore start of stringregular expression escape if not preceded by anything(每個都沒有用)這樣的查詢,我決定來問你們的幫助。所以,這裏是我的問題:

是否有可能表示查找字符串的結束和開始?(或者,一個空的字符將正常工作。)

我已經嘗試過^$\b字符,以便我的表情看起來像(?<!(^|\b|\\))\\(?=($|\b|)),但這並沒有影響。 (我也試過空文字,如(?<!(|\\))\\(?=(|))。)

任何幫助是非常,非常感謝。提前致謝!

+0

那你將會看到' 「\測試\\」'輸出? – dasblinkenlight

+0

是否可以使用表示''foo \\''的字符串(是帶有兩個反斜槓的字面值)?如果是的話它會如何看起來像讓我們說'foo的參數?當我們想逃離太空時(應該用什麼來代替'???')?會不會是'foo \\\\\\ bar'?如果我們不想逃離太空,它應該看起來像'foo \\\\ bar'嗎?如果是這樣,那麼你的分裂條件可能是錯誤的'(?<!(?<!\\\\)\\\\)'。順便說一句,這個條件與'(?<!\\\\\\\\)'或者更簡單的'(?<!(\\\\){2})'相同。 – Pshemo

+0

這個問題會更容易回答,如果我們將有什麼樣的數據,你允許你的程序的確定性和不應該出現什麼樣的數據。我可能有一個如何幫助你一些想法,但我需要知道,如果一些字符串可能與否,比如就像''ABC \ \\\高清\\\\\ GHI \ \\ \\\ JK LMN串\''可能嗎?如果不是完全的哪個部分?如果是的話,你想如何解析這句話?如果你會刪除不正確的部分如何正確的句子看起來像它應該如何解析? – Pshemo

回答

1

不能在lookarounds使用$^因爲:

  • lookarounds字面上試圖說,我們可以之前或當前位置後,符合一定的規律性,而:
  • $^是不是真的可以匹配,他們自己是SIM卡簾布斷言太(斷言,我們分別在(:開始輸入)。

因此,你甚至可以看到他們作爲簡單的特定環視。簡寫爲(?<=^)^(?=$)$

在你的情況,你應該簡單地處理這種情況,其中一個\是在生產線的最後通過檢查附加條件\\$在您正則表達式,這成爲:

((?<!\\)\\(?=)|\\$) 

...或者,如一個的JavaString((?<!\\\\)\\\\(?=)|\\\\$)

看到一個工作示例here on regex101

+0

啊,好的。非常感謝你! – afistofirony

0

最簡單的解決方案是將所有\視爲特殊字符,如Java中的String。通過這種方式創建\文字,您需要使用兩個\\

,而不是找地方分裂你可以只創建規則,會接受這是從

  • 字母數字建設作爲標記字符串現在 - 例如\\w
  • 兩個反斜槓
  • 或之後與空間反斜槓它

這種組合的模式可能看起來像

Pattern p = Pattern.compile("(\\w+|(\\\\){2}|\\\\\\s)+"); 

我們「正常化」這你就只需要一個反斜槓來替換兩個反斜槓和替換反斜槓的其餘部分(單一個),什麼也沒有。你可以用這個表達式的

replaceAll("(\\\\)\\\\|\\\\", "$1") 

想法做到這一點是首先嚐試他們的第一個找到兩個反斜槓,地點在第1組,所以我們可以用這第一個反斜槓替換它們。由於已經匹配的反斜槓在同一遍中不能再次找到(匹配),因此單個匹配的反斜槓必須是未轉義的反斜槓,我們希望擺脫它們。因爲對他們來說正則表達式的唯一正確的一側的replaceAll會發現左邊是空的,這意味着將有1組沒有匹配這樣$1將返回空字符串,因爲我們想(取代單\與空字符串)。

這裏是例如該解決方案的

String data = "these\\ are\\ \\\\toge\\\\ther and these\\\\ \\not\\"; 
System.out.println("user input = "+data); 
System.out.println("--------------"); 

Pattern p = Pattern.compile("(\\w+|(\\\\){2}|\\\\\\s)+"); 
//find only combination of letters or two backslashes or backslash and space 
Matcher m = p.matcher(data); 
while (m.find()) 
    System.out.println(m.group().replaceAll("(\\\\)\\\\|\\\\", "$1")); 

輸出:

user input = these\ are\ \\toge\\ther and these\\ \not\ 
-------------- 
these are \toge\ther 
and 
these\ 
not 
相關問題