2016-10-31 35 views
0

我正在用Java編寫一個應用程序,顯示文件名中的第一個單詞與用戶定義的字符串相匹配的文件列表,然後根據一些首選項刪除或重新排列它們。我目前正處於尋找找到我的文件的好方法的階段。使用this Java Tutorial我結束了這樣的事情:Java正則表達式和PathMatcher

Path source = Paths.get(sourceText.getText()); 
Path dest = Paths.get(destText.getText()); 

System.out.println("Source:" + source.toString()); 
System.out.println("P/N: " + partNoText.getText()); 

String matchString = "glob:**" + partNoText.getText() + "*"; 

System.out.println("Matching: " + matchString); 

fileFinder = new FileFinder(matchString); 

try { 
    Files.walkFileTree(source, fileFinder); 
} catch (IOException e1) { 
    e1.printStackTrace(); 
} 
for (Path path : fileFinder.getResult()) { 
    System.out.println("Moving: " + path.getFileName()); 
    Path target = Paths.get(dest.toString() + "\\" + path.getFileName()); 

    try { 
     Files.move(path, target, REPLACE_EXISTING); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
} 

其中FileFinder延伸SimpleFileVisitor並擁有本visitFile方法:

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
    System.out.println(file.toString()); 
    System.out.println(fileMatcher.matches(file)); 
    if (fileMatcher.matches(file)) { 
     result.add(file); 
     return FileVisitResult.CONTINUE; 
    } 
    return FileVisitResult.CONTINUE; 
} 

我對這個問題的是,水珠會拿起任何文件,其中文件名包含零件編號。以任何方式。所以如果我的文件被稱爲「12345 RevA真的很大的第二部分:電動Bugaloo」,那麼如果用戶輸入「1」或「123」或「Bugaloo」,字符串就會匹配。理想情況下,只有當用戶輸入「12345」時纔會匹配。

我試着將我的matchString切換爲"regex: .*" + partNoText + "\\b",它適用於從this other Java Tutorial修改過的正則表達式測試工具。我究竟做錯了什麼? PathMatcher的工作方式與常規的Matcher不同嗎?

P.S.任何具有「Text」字樣的變量,如sourceTextpartNoText都是JTextFields。 Hopefull是代碼的唯一部分,大部分內容都不清楚。

+1

文件名_globbing_是_ **不是** _正則表達式; globbing比正則表達式更受限制。另外,作爲一個glob的'foo *'匹配foo-with-anything-after,相當於一個正則表達式將是'foo。*'= foo,後跟任意一個char'.'零次或多次''''' –

+0

_「理想情況下,只有當用戶輸入」12345「時纔會匹配。」_ _部件號_always_是文件名的第一部分嗎?所有零件號碼都是_exactly_ 5位數字嗎?零件號碼_always_後跟一個空格?有一個精確的定義可以幫助你找到一個好的正則表達式。我不認爲globbing會在這種情況下做到這一點,儘管你可以通過glob來減少匹配空間,然後正則表達式匹配globbing找到的東西。 –

+0

@StephenP對於你的第一個評論,我的理解是globbing和regex是兩種不同的方法,可以創建廣義字符串來匹配。你可以從我的問題的底部看到,我決定從globbing改爲正則表達式由於其侷限性 –

回答

1

「PathMatcher的工作方式與常規匹配器不同嗎?」
是的。 a PathMatcher與文件名混合使用[1],而Matcher使用正則表達式

請參閱What Is a Glob?的鏈接教程,並將其與java.util.regex.Pattern的文檔進行比較。
Globbing比正則表達式匹配更受限制。

如果你有一個嚴格的文件命名約定,嚴格遵守你可能可以使用globbing(我收回了我以前的評論的最後一部分)。

比方說,你的文件被命名爲
numeric part number - space - optional revision & space - description

也就是說,零件號可以具有可變的位數,但部件編號後的空間是必需的,總是存在。

所以你的榜樣「12345雷瓦真正的大第2部分:電動Bugaloo」適合與partNum == 12345,修訂= 「雷瓦」,說明= 「真正的大第2部分:電動Bugaloo」

一用戶輸入部件號P/N: 123作爲變量userPN和構造一個水珠作爲
String glob = userPN + " *";導致水珠等於"123 *"
這將匹配12345,你的願望,這是因爲空間的後3將不匹配4 。

如果在文件名中的部件編號後所需的空間,但接踵而來的是總是字母,無論是修訂或說明,您可以構建一個水珠爲
String glob = userPN + "[A-Z,a-z]*";讓水珠= 123[A-Z,a-z]*也不會匹配12345,因爲字母必須跟在123之後,並且4不在該字符範圍內。

你可以讓你的角色範圍比較複雜,說[A-Z,a-z, ]可選空間,根據您的需要,這一切真的可以歸結爲你的文件命名約定。你需要非常精確地陳述這個慣例並堅持它。


[1] PathMatcher可以使用通配符代替一個正則表達式,如果你調用FileSystem.getPathMatcher(String)時指定的「語法」爲regex。這將是類似的東西

FileSystem fs = FileSystems.getDefault(); 
PathMatcher pm = fs.getPathMatcher("regex:\\d{5}\\s.*"); 
+0

如果您閱讀我發佈的第一個鏈接,請在「什麼是glob?」鏈接下面是一條線,指出正則表達式可以與PathMatchers一起使用。這就是爲什麼我在匹配語句中使用「正則表達式:...」而不是「glob:...」。但是,這看起來好像讓我過度複雜了。感謝您爲我簡化它。 –

+0

@Eric - 我看到_「Glob語法易於使用且靈活,但如果您願意,還可以使用正則表達式或正則表達式語法。」但是沒有看到任何方法可以實現。我現在已經找到[getPathMatcher](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-),這是你的地方可以指定''regex:「作爲_syntaxAndPattern_參數。知道這可能會使未來的讀者受益。 –

0

我認爲你去它上面非常複雜的方式。當你不尋找事件時,爲什麼你會首先使用pat Marc her。

通過遍歷文件樹和每個目錄迭代目錄流來匹配您的glob會容易得多。