Is there already a lib to parse a line of string with a pattern and generate key-value map or a record?

Hi, I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already. Sample: Input line: "2019/04/17 17:27 User magicloud runs command ls." Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}." Output: toList [ ("year", "2019"), ("month", "04") , etc ] -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com.

I would use Dhall: https://dhall-lang.org/ (I can answer questions but the documentation is reasonably good) Cheers, Vanessa On 4/17/19 4:29 AM, Magicloud Magiclouds wrote:
Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Sorry, I am not sure how this relates to my thought? I want a parsing tool.
On Wed, Apr 17, 2019 at 8:11 PM Vanessa McHale
I would use Dhall: https://dhall-lang.org/
(I can answer questions but the documentation is reasonably good)
Cheers, Vanessa
On 4/17/19 4:29 AM, Magicloud Magiclouds wrote:
Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com.

I think specific formats can be parsed with attoparsec (Data.Attoparsec.Text): p = do year <- yearP char '/' month <- monthP char '/' .... return (year, month, ...) You may also use cassava to parse csv-like files, or Frames for type-safe parsing. With Frames you may custom readers ( http://acowley.github.io/Frames/#orgfa57664 ) with complex pattern-matching, this will require typing skills though. ср, 17 апр. 2019 г. в 12:30, Magicloud Magiclouds < magicloud.magiclouds@gmail.com>:
Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Sincerely, Stanislav Chernichkin.

Thanks. I am familiar with this kind of usage (attoparsec). But it is
still somehow complex and not flexible.
Let me see what Frame can do.
On Wed, Apr 17, 2019 at 9:46 PM Станислав Черничкин
I think specific formats can be parsed with attoparsec (Data.Attoparsec.Text):
p = do year <- yearP char '/' month <- monthP char '/' .... return (year, month, ...)
You may also use cassava to parse csv-like files, or Frames for type-safe parsing. With Frames you may custom readers ( http://acowley.github.io/Frames/#orgfa57664 ) with complex pattern-matching, this will require typing skills though.
ср, 17 апр. 2019 г. в 12:30, Magicloud Magiclouds
: Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Sincerely, Stanislav Chernichkin.
-- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com.

I think you're looking for a scanf (well known in C) like function. A quick search give me: https://hackage.haskell.org/package/scanf https://hackage.haskell.org/package/xformat I haven't used either of them, so I can't recommend one. Regards, Frank Dedden On Wed, Apr 17, 2019 at 10:32:07PM +0800, Magicloud Magiclouds wrote:
Thanks. I am familiar with this kind of usage (attoparsec). But it is still somehow complex and not flexible.
Let me see what Frame can do.
On Wed, Apr 17, 2019 at 9:46 PM Станислав Черничкин
wrote: I think specific formats can be parsed with attoparsec (Data.Attoparsec.Text):
p = do year <- yearP char '/' month <- monthP char '/' .... return (year, month, ...)
You may also use cassava to parse csv-like files, or Frames for type-safe parsing. With Frames you may custom readers ( http://acowley.github.io/Frames/#orgfa57664 ) with complex pattern-matching, this will require typing skills though.
ср, 17 апр. 2019 г. в 12:30, Magicloud Magiclouds
: Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Sincerely, Stanislav Chernichkin.
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

scanf looks interesting. Closer to my case. Thanks.
Neil, the formation looks OK in GMail. The lib gives me some other
thoughts. Thanks.
On Wed, Apr 17, 2019 at 11:24 PM Frank Dedden
I think you're looking for a scanf (well known in C) like function. A quick search give me: https://hackage.haskell.org/package/scanf https://hackage.haskell.org/package/xformat
I haven't used either of them, so I can't recommend one.
Regards, Frank Dedden
On Wed, Apr 17, 2019 at 10:32:07PM +0800, Magicloud Magiclouds wrote:
Thanks. I am familiar with this kind of usage (attoparsec). But it is still somehow complex and not flexible.
Let me see what Frame can do.
On Wed, Apr 17, 2019 at 9:46 PM Станислав Черничкин
wrote: I think specific formats can be parsed with attoparsec (Data.Attoparsec.Text):
p = do year <- yearP char '/' month <- monthP char '/' .... return (year, month, ...)
You may also use cassava to parse csv-like files, or Frames for type-safe parsing. With Frames you may custom readers ( http://acowley.github.io/Frames/#orgfa57664 ) with complex pattern-matching, this will require typing skills though.
ср, 17 апр. 2019 г. в 12:30, Magicloud Magiclouds
: Hi,
I saw this function in some web tools, pretty useful when parsing log or so. So I wonder if Haskell has similar libs already.
Sample:
Input line: "2019/04/17 17:27 User magicloud runs command ls."
Pattern: "${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}."
Output: toList [ ("year", "2019"), ("month", "04") , etc ]
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Sincerely, Stanislav Chernichkin.
-- 竹密岂妨流水过 山高哪阻野云飞
And for G+, please use magiclouds#gmail.com. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com.

I’m a fan of |regex-applicative|. It’s a combinator library modelled on the parsec family but because it parses only regular languages rather than context-free ones, it’s a bit simpler to use and is a better match for some tasks. It uses |OverloadedStrings| to make it easier to include literal string matches and provides a non-greedy repeating combinator called |few| that avoids having to specify exclusive matches. I think it solves this problem quite nicely: |{-# LANGUAGE OverloadedStrings #-} import Text.Regex.Applicative -- This is just <*> with right associativity (<&>) :: Applicative f => f (a -> b) -> f a -> f b (<&>) = (<*>) infixr 3 <&> type Item = (String, String) item :: String -> RE Char ([Item] -> [Item]) item key = (:) . (,) key <$> few anySym -- ${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}. pattern :: RE Char [Item] pattern = item "year" <* "/" <&> item "month" <* "/" <&> item "day" <* " " <&> item "hour" <* ":" <&> item "minute" <* " User " <&> item "username" <* " runs command " <&> item "command" <* "." <&> pure [] input :: String input = "2019/04/17 17:27 User magicloud runs command ls." output :: Maybe [Item] output = match pattern input -- Just [("year","2019"),("month","04"),("day","17"),("hour","17"),("minute","27"),("username","magicloud"),("command","ls")] | (Also available as a gist https://gist.github.com/neilmayhew/e4fc90b7eaeb7bbcfeb6d6938544ecc9.) Obviously the combinator version is less compact and therefore could be considered less readable, but the implementation details could probably be tweaked a bit. It would also be relatively easy to write a quasi-quoter that turns the original input syntax (with |${variable}|) into the equivalent I’ve shown here.

I'm sorry, the formatting got mangled in my last message, because I was using MarkdownHere. I'll try again without converting it to HTML. I'm a fan of `regex-applicative`. It's a combinator library modelled on the parsec family but because it parses only regular languages rather than context-free ones, it's a bit simpler to use and is a better match for some tasks. It uses `OverloadedStrings` to make it easier to include literal string matches and provides a non-greedy repeating combinator called `few` that avoids having to specify exclusive matches. I think it solves this problem quite nicely: ```haskell {-# LANGUAGE OverloadedStrings #-} import Text.Regex.Applicative -- This is just <*> with right associativity (<&>) :: Applicative f => f (a -> b) -> f a -> f b (<&>) = (<*>) infixr 3 <&> type Item = (String, String) item :: String -> RE Char ([Item] -> [Item]) item key = (:) . (,) key <$> few anySym -- ${year}/${month}/${day} ${hour}:${minute} User ${username} runs command ${command}. pattern :: RE Char [Item] pattern = item "year" <* "/" <&> item "month" <* "/" <&> item "day" <* " " <&> item "hour" <* ":" <&> item "minute" <* " User " <&> item "username" <* " runs command " <&> item "command" <* "." <&> pure [] input :: String input = "2019/04/17 17:27 User magicloud runs command ls." output :: Maybe [Item] output = match pattern input -- Just [("year","2019"),("month","04"),("day","17"),("hour","17"),("minute","27"),("username","magicloud"),("command","ls")] ``` (Also available as a [gist](https://gist.github.com/neilmayhew/e4fc90b7eaeb7bbcfeb6d6938544ecc9).) Obviously the combinator version is less compact and therefore could be considered less readable, but the implementation details could probably be tweaked a bit. It would also be relatively easy to write a quasi-quoter that turns the original input syntax (with `${variable}`) into the equivalent I've shown here.
participants (5)
-
Frank Dedden
-
Magicloud Magiclouds
-
Neil Mayhew
-
Vanessa McHale
-
Станислав Черничкин