2

次のように、バイト文字列内の連続するすべてのタブを単一のタブに置き換える必要があります。

"___\t___\t\t___\t\t\t___"

になる

"___\t___\t___\t___"

やり方がわかりません

30 分ほど考え抜いた後、最初に出現した二重タブを次のように置き換えることができました (これでさえ実際には間違っています。空の文字列にタブが追加されます)。

import qualified Pipes.ByteString as PB
import qualified Data.ByteString as B

removeConsecutiveTabs =
  PB.break (== tab) . mapped %~ \p -> do
    yield (B.singleton tab)
    PB.dropWhile (== tab) p

ただし、連続するタブをすべて置き換える方法はまだわかりません。

4

3 に答える 3

2

これを試して:

{-# LANGUAGE OverloadedStrings #-}

import Pipes
import qualified Pipes.Prelude as P
import qualified Pipes.ByteString as PB
import           Data.ByteString (ByteString)
import Control.Lens hiding (each)

cleanTabs p = do
  p1 <- view (PB.span (/= 9)) p
  x <- lift $ next p1
  case x of
    Left r -> return r
    Right (a, p2) -> do
      yield "\t"
      let p3 = PB.dropWhile (== 9) (yield a >> p2)
      cleanTabs p3

source :: Monad m => Producer ByteString m ()
source = each [ "this", "is\t an", "\t\texample\t", "\t.", "\t\tmiddle\t", "\there"]

example = do
  putStrLn $ "input: " ++ (show $ P.toList source)
  putStrLn $ "output:" ++ (show $ P.toList (cleanTabs source))
于 2015-08-23T04:40:27.067 に答える
1

キーは、バイト文字列チャンクの 1 つではなく、バイト ストリームで動作しています。packこれは、pipes-bytestring (および pipes-text) から実行できます。これは、特に洗練されていないデモです。

{-# LANGUAGE OverloadedStrings #-}

import Pipes
import qualified Pipes.ByteString as PB
import qualified Data.ByteString as B
import Control.Monad
import Control.Lens (over)

test byst = runEffect $
    removingConsecutiveTabs (PB.fromLazy byst) >-> PB.stdout

removingConsecutiveTabs :: Monad m
                        => Producer B.ByteString m r
                        -> Producer B.ByteString m r
removingConsecutiveTabs = over PB.pack tabGatekeeper

tabGatekeeper :: Monad m => Producer PB.Word8 m r -> Producer PB.Word8 m r
tabGatekeeper = go False
    where
    go wasTab stream = do
        ex <- lift $ next stream
        case ex of
            Left r -> return r
            Right (x, stream') -> do
                let thisIsATab = w8IsTab x
                unless (wasTab && thisIsATab) $ yield x
                go thisIsATab stream'

    w8IsTab x = toEnum (fromIntegral x) == '\t'
GHCi> :set -XOverloadedStrings
GHCi> test "___\t___\t\t___\t\t\t___\n"
___ ___ ___ ___
于 2015-08-23T02:47:41.190 に答える