试图编写一个返回我计算机外部IP地址的模块。使用Network.Wreq get函数,然后应用一个lense来获得responseBody,最后类型是Data.ByteString.Lazy.Internal.ByteString。由于我希望筛选出结果体的尾部"\n“,因此希望随后将其用于正则表达式。问题: regex库不接受看似非常特定的ByteString类型,而且我也无法将其转换为String。
以下是我迄今为止的薄弱尝试(未编译)。
{-# LANGUAGE OverloadedStrings #-}
module ExtIp (getExtIp) where
import Network.Wreq
import Control.Lens
import Data.BytesString.Lazy
import Text.Regex.Posix
getExtIp :: IO String
getExtIp = do
r <- get "http://myexternalip.com/raw"
let body = r ^. responseBody
let addr = body =~ "[^\n]*\n"
return (addr)很明显,我的问题是:如何将有趣的特殊ByteString转换为String?解释我如何能够自己处理这样的问题也是值得赞赏的。我尝试使用unpack和toString,但是不知道导入什么来获取这些函数(如果存在的话)。
作为一个非常零星的haskell用户,我也想知道是否有人能向我展示haskell定义这样一个函数的惯用方法。毕竟,我在这里展示的版本没有考虑可能的运行时错误/异常。
发布于 2016-06-01 15:46:38
我只是不明白为什么您坚持使用String,因为您手头已经有了一个ByteString,这是一个更快/更有效的实现。导入regex几乎不会给您带来任何好处--对于解析ip地址,我将使用attoparsec,这对ByteString的工作非常有用。
这里有一个版本,它不使用regex,但返回一个字符串-注意,我没有编译它,因为我现在没有haskell设置。
{-# LANGUAGE OverloadedStrings #-}
module ExtIp (getExtIp) where
import Network.Wreq
import Control.Lens
import Data.ByteString.Lazy.Char8 as Char8
import Data.Char (isSpace)
getExtIp :: IO String
getExtIp = do
r <- get "http://myexternalip.com/raw"
return $ Char8.unpack $ trim (r ^. responseBody)
where trim = Char8.reverse . (Char8.dropWhile isSpace) . Char8.reverse . (Char8.dropWhile isSpace)发布于 2016-06-01 15:43:53
简单回答:使用unpack from Data.ByteString.Lazy.Char8
较长的答覆:
通常,当您想要将ByteString (任意种类)转换为字符串或文本时,您必须指定编码--例如UTF-8或Latin1等等。
在检索HTML页面时,您应该使用的编码可能会以<meta ...>标记的形式出现在内容类型标题中或响应体本身中。
或者,你只需猜测身体的编码是什么。
在您的情况下,我假设您正在访问像http://whatsmyip.org这样的站点,您只需要解析出您的IP地址。因此,不检查头部或查看HTML,使用的安全编码将是Latin1。
若要通过编码将ByteStrings转换为文本,请查看Data.Text.Encoding中的函数。
例如,decodeLatin1函数。
https://stackoverflow.com/questions/37571939
复制相似问题