2017-09-16 31 views
0

我試圖做一個簡單的Haskell程序,將採取看起來像someFilenameHere0035.xml和返回0035任何行。我的樣本輸入文件input.txt中,應該是這樣的:如何在Haskell中使用此正則表達式?

someFilenameHere0035.xml 
anotherFilenameHere4465.xml 

並運行:cat input.txt | runhaskell getID.hs應該返回:

0035 
4465 

我有這麼多的困難,搞清楚了這一點。這是我到目前爲止有:

import Text.Regex.PCRE 

getID :: String -> [String] 
getID str = str =~ "([0-9]+)\\.xml" :: [String] 

main :: IO() 
main = interact $ unlines . getID 

但我得到一個錯誤信息,我不知道在所有:

• No instance for (RegexContext Regex String [String]) 
arising from a use of ‘=~’ 
• In the expression: str =~ "([0-9]+)\\.xml" :: [String] 
    In an equation for ‘getID’: 
    getID str = str =~ "([0-9]+)\\.xml" :: [String] (haskell-stack-ghc) 

我覺得我真的很接近,但我不知道從這往哪兒走。我究竟做錯了什麼?

+1

如果這是爲了學習Haskell:太棒了!否則,看起來你可能只想在這裏拋出標準的命令行工具。 'grep -o'[0-9] \ + \。xml'| sed's/.xml //'似乎可以工作,如果你不介意它看起來不那麼容易理解,你可以用一個'sed'命令來完成。 –

回答

1

首先你只想要號碼部分,所以我們可以擺脫\\.xml

正則表達式-PCRE庫定義了一個實例RegexContext Regex String String但不RegexContext Regex String [String]因此錯誤。

所以,如果我們將類型簽名更改爲String -> String那麼該錯誤是照顧。

unlines預計[字符串]所以要考什麼,我們必須在這一點上我寫了一個快速功能封裝在一個列表其參數(有可能是一個更好的方式來做到這一點,但是這不是問題的問題):

toList :: a -> [a] 
toList a = [a] 

main = interact $ unlines . toList . getID輸出0035運行你的命令,所以我們幾乎沒有。

getID傳遞文件內容的字符串,這些字符串被\n字符方便地分開。因此,我們可以使用Data.List.Split庫中的splitOn "\n"來獲取我們的.xml文件列表。

然後我們只需要在該列表上映射getID(不再需要toList)。

這給我們:

import Text.Regex.PCRE 
import Data.List.Split 

getID :: String -> String 
getID str = str =~ "([0-9]+)" 

main :: IO() 
main = interact $ unlines . map getID . splitOn "\n" 

這給了我所需要的輸出,當我運行命令。

希望這有助於:)

+0

最初的正則表達式可能是故意選擇的,例如,如果他們期待一個可能的文件名是'foo3bar4.xml'。 –

+0

@DanielWagner如果是這種情況,那麼示例input.txt文件應該包含這種情況。我只是提供了一些爲示例輸入提供所需輸出的內容。 –

相關問題