2017-09-16 12 views
0

私はsomeFilenameHere0035.xmlのような行を取り、0035を返す単純なHaskellプログラムを作ろうとしています。私のサンプル入力ファイル、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

これはハスケルを学習するためのものです。さもなければ、これで標準のコマンドラインツールを投げたいかもしれないようです。 'grep -o '[0-9] \ + \。xml' | sedの/ .xml // ''はうまくいくと思われます。少し分かりにくいのを気にしなければ、おそらく単一の 'sed'コマンドで実行できます。 –

答えて

1

まず数字部分がほしいから、\\.xmlを取り除くことができます。

regex-pcreライブラリではRegexContext Regex String Stringのインスタンスが定義されていますが、RegexContext Regex String [String]ではなくエラーです。

したがって、タイプシグネチャをString -> Stringに変更すると、そのエラーは処理されます。

unlinesを期待[文字列]私たちは、私は(そこにそれを行うためのよりよい方法は、おそらくですが、それが問題のポイントはありません)リスト内の引数をラップ迅速な機能を書いた、この時点で持っていたものをテストするには:

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

main = interact $ unlines . toList . getIDの出力コマンドを実行すると、ほぼ完了です。

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そうである場合、example.txtファイルの例にそのような場合が含まれているはずです。私は、サンプル入力に対して望ましい出力を与えたものを提供しました。 –

関連する問題