2012-01-30 16 views
17

क्या हास्केल में रेगेक्स के साथ खोज-और-प्रतिस्थापन करने के लिए उच्च स्तरीय एपीआई है? विशेष रूप से, मैं Text.Regex.TDFA या Text.Regex.Posix पैकेज देख रहा हूं। वास्तव में टाइप के बारे में कुछ है कि मैं चाहता हूँ:हास्केल रेगेक्स पुस्तकालयों के साथ प्रतिस्थापन/प्रतिस्थापन

f :: Regex -> (ResultInfo -> m String) -> String -> m String 

इसलिए, उदाहरण के लिए, "बिल्ली" के साथ "कुत्ता" इकाई के साथ बदलने के लिए आप

runIdentity . f "dog" (return . const "cat") -- :: String -> String 

लिख सका करना और अधिक उन्नत बातें, जैसे गिनती घटनाएं, आदि

इसके लिए हास्केल दस्तावेज़ों में काफी कमी है। कुछ निम्न-स्तरीय एपीआई नोट here हैं।

उत्तर

4

मैं किसी भी मौजूदा समारोह है कि इस कार्यक्षमता बनाता है के बारे में पता नहीं है, लेकिन मुझे लगता है कि मैं AllMatches [] (MatchOffset, MatchLength) instance of RegexContent की तरह कुछ का उपयोग कर इसे अनुकरण करने के लिए पहुंचते हैं:

replaceAll :: RegexLike r String => r -> (String -> String) -> String -> String 
replaceAll re f s = start end 
    where (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s 
     go (ind,read,write) (off,len) = 
      let (skip, start) = splitAt (off - ind) read 
       (matched, remaining) = splitAt len matched 
      in (off + len, remaining, write . (skip++) . (f matched ++)) 

replaceAllM :: (Monad m, RegexLike r String) => r -> (String -> m String) -> String -> m String 
replaceAllM re f s = do 
    let go (ind,read,write) (off,len) = do 
     let (skip, start) = splitAt (off - ind) read 
     let (matched, remaining) = splitAt len matched 
     replacement <- f matched 
     return (off + len, remaining, write . (skip++) . (replacement++)) 
    (_, end, start) <- foldM go (0, s, return) $ getAllMatches $ match re s 
    start end 
28

कैसे पैकेज पाठ में subRegex के बारे में .Regex?

Prelude Text.Regex> :t subRegex 
subRegex :: Regex -> String -> String -> String 

Prelude Text.Regex> subRegex (mkRegex "foo") "foobar" "123" 
"123bar" 
1

शायद यह दृष्टिकोण आपको फिट कर सकता है।

import Data.Array (elems) 
import Text.Regex.TDFA ((=~), MatchArray) 

replaceAll :: String -> String -> String -> String   
replaceAll regex new_str str = 
    let parts = concat $ map elems $ (str =~ regex :: [MatchArray]) 
    in foldl (replace' new_str) str (reverse parts) 

    where 
    replace' :: [a] -> [a] -> (Int, Int) -> [a] 
    replace' new list (shift, l) = 
     let (pre, post) = splitAt shift list 
     in pre ++ new ++ (drop l post) 
3

@ rampion के जवाब के आधार पर, लेकिन टाइपो तय साथ तो यह सिर्फ <<loop>> नहीं करता है:

replaceAll :: Regex -> (String -> String) -> String -> String 
replaceAll re f s = start end 
    where (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s 
     go (ind,read,write) (off,len) = 
      let (skip, start) = splitAt (off - ind) read 
       (matched, remaining) = splitAt len start 
      in (off + len, remaining, write . (skip++) . (f matched ++)) 
1

आप Data.Text.ICU.Replace module से replaceAll उपयोग कर सकते हैं।

Prelude> :set -XOverloadedStrings 
Prelude> import Data.Text.ICU.Replace 
Prelude Data.Text.ICU.Replace> replaceAll "cat" "dog" "Bailey is a cat, and Max is a cat too." 
"Bailey is a dog, and Max is a dog too." 
संबंधित मुद्दे