2010-10-02 20 views
21

Mặc dù số lượng ridiculously lớn của regex phù hợp với động cơ cho Haskell, là người duy nhất tôi có thể thấy rằng sự thay thế sẽ Text.Regex, trong đó, trong khi phong nha, đang thiếu một vài điều tôi muốn từ PCRE. Có bất kỳ gói dựa trên pcre mà sẽ làm thay thế, hoặc tôi bị mắc kẹt với điều này?Haskell thay regex

+2

Câu hỏi hay, tôi đã chạy vào cùng một vấn đề. –

+2

okay, vâng, tôi đã viết của riêng tôi dựa trên 'Text.Regex.PCRE.Light', mặc dù nó cổng độc đáo với hầu hết các triển khai khác. – muhmuhten

+5

Đăng câu trả lời nếu nó giải quyết được vấn đề. – kennytm

Trả lời

3

API biểu thức chính quy trong cơ sở regex là chung cho vùng chứa ký tự khớp. Làm một số loại nối chung để thực hiện thay thế sẽ rất khó để làm cho hiệu quả. Tôi không muốn cung cấp một thói quen chung chung crappy.

Viết một chức năng nhỏ để thực hiện thay thế chính xác cách bạn muốn chỉ là ý tưởng tốt hơn và có thể được viết để khớp với vùng chứa của bạn.

4

Tôi không nghĩ rằng "chỉ cuộn của riêng bạn" là câu trả lời hợp lý cho những người đang cố gắng hoàn thành công việc thực tế, trong một khu vực nơi mọi ngôn ngữ hiện đại khác có cách nhỏ để thực hiện việc này. Bao gồm Đề án. Vì vậy, đây là một số tài nguyên thực tế; mã của tôi là từ một dự án mà tôi đã cố gắng để thay thế "qql foo bar baz qq" với văn bản dựa trên gọi một chức năng trên các công cụ bên trong qq "khung", bởi vì lý do.

Lựa chọn tốt nhất: PCRE nặng:

 let newBody = gsub [re|\s(qq[a-z]+)\s(.*?)\sqq\s|] (unWikiReplacer2 titles) body in do 
[snip] 
unWikiReplacer2 :: [String] -> String -> [String] -> String 
unWikiReplacer2 titles match subList = case length subList > 0 of 
     True -> " --" ++ subList!!1 ++ "-- " 
     False -> match 

Lưu ý rằng PCRE nặng trực tiếp hỗ trợ chức năng dựa vào thay thế, với bất kỳ loại chuỗi. Thật tốt.

Một lựa chọn khác: PCRE ánh sáng với một chức năng nhỏ mà làm việc nhưng không phải là chính xác performant:

let newBody = replaceAllPCRE "\\s(qq[a-z]+)\\s(.*?)\\sqq\\s" (unWikiReplacer titles) body in do 
[snip] 
unWikiReplacer :: [String] -> (PCRE.MatchResult String) -> String 
unWikiReplacer titles mr = case length subList > 0 of 
     True -> " --" ++ subList!!1 ++ "-- " 
     False -> PCRE.mrMatch mr 
    where 
     subList = PCRE.mrSubList mr 

-- A very simple, very dumb "replace all instances of this regex 
-- with the results of this function" function. Relies on the 
-- MatchResult return type. 
-- 
-- https://github.com/erantapaa/haskell-regexp-examples/blob/master/RegexExamples.hs 
-- was very helpful to me in constructing this 
-- 
-- I also used 
-- https://github.com/jaspervdj/hakyll/blob/ea7d97498275a23fbda06e168904ee261f29594e/src/Hakyll/Core/Util/String.hs 
replaceAllPCRE :: String    --^Pattern 
      -> ((PCRE.MatchResult String) -> String) --^Replacement (called on capture) 
      -> String    --^Source string 
      -> String    --^Result 
replaceAllPCRE pattern f source = 
    if (source PCRE.=~ pattern) == True then 
     replaceAllPCRE pattern f newStr 
    else 
     source 
    where 
     mr = (source PCRE.=~ pattern) 
     newStr = (PCRE.mrBefore mr) ++ (f mr) ++ (PCRE.mrAfter mr) 

của người khác sửa chữa: http://0xfe.blogspot.com/2010/09/regex-substitution-in-haskell.html

Một số khác, thời gian này được nhúng trong một thư viện lớn : https://github.com/jaspervdj/hakyll/blob/master/src/Hakyll/Core/Util/String.hs

Gói khác cho mục đích này: https://hackage.haskell.org/package/pcre-utils