首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用管道将双制表符替换为单个制表符?

如何使用管道将双制表符替换为单个制表符?
EN

Stack Overflow用户
提问于 2015-08-22 14:17:58
回答 3查看 189关注 0票数 2

我需要用单个选项卡替换字节字符串中的所有连续选项卡,如下所示:

代码语言:javascript
复制
"___\t___\t\t___\t\t\t___"

变成了

代码语言:javascript
复制
"___\t___\t___\t___"

我不知道该怎么做。

经过半个小时的计算,我成功地替换了第一次出现双制表符,就像这样(甚至这也是错误的--它为空字符串添加了一个选项卡):

代码语言:javascript
复制
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

但是,我仍然不知道如何替换所有出现的连续选项卡。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-23 04:40:27

试试这个:

代码语言:javascript
复制
{-# 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))
票数 2
EN

Stack Overflow用户

发布于 2015-08-23 02:47:41

键是在字节流上操作,而不是字节串块中的一个。这可以通过管道-字节串(和管道-文本)通过pack完成。下面是一个并不特别复杂的演示:

代码语言:javascript
复制
{-# 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'
代码语言:javascript
复制
GHCi> :set -XOverloadedStrings
GHCi> test "___\t___\t\t___\t\t\t___\n"
___ ___ ___ ___
票数 1
EN

Stack Overflow用户

发布于 2015-08-22 15:12:24

这里有一个解决方案,它不使用PB.break,但只使用基本的管道操作。问题之一是,数据以块形式出现,您必须跟踪最后一个块是否以选项卡结尾:

代码语言:javascript
复制
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}

module Lib5
where

import Pipes
import Pipes.ByteString
import qualified Data.ByteString.Char8 as BS
import Control.Monad

printAll = forever $ do a <- await; lift $ putStrLn $ "got: " ++ show a

endsWith bs ch = BS.length bs > 0 && BS.last bs == ch

convertDoubleTabs = await >>= go0

-- no precediing tab
go0 b = do
  let (pre,post) = BS.breakSubstring "\t\t" b
  yield pre
  if BS.length post == 0
    then if endsWith pre '\t'
            then await >>= go1
            else await >>= go0
    else do yield "\t"
            go0 (BS.drop 2 post)

-- last chunk ended in a tab
go1 b = do
  if BS.length b == 0
    then await >>= go1
    else if BS.index b 0 == '\t'
            then go0 (BS.drop 1 b)
            else go0 b

example1 = runEffect $ each [ "this", "is\t an", "\t\texample\t", "\t."] 
                       >-> convertDoubleTabs
                       >-> printAll

如果我用Pipes.ByteString和镜头找到一个解决方案的话,我会添加到这个答案中。

若要转换所有连续选项卡,请执行以下操作:

代码语言:javascript
复制
convertTabs = await >>= go0
  where
    go0 b = do
      let (pre,post) = BS.break (== '\t') b
      yield pre
      if BS.length post == 0
        then await >>= go0
        else do yield "\t"
                go1 post

    go1 b = do
      let b' = BS.dropWhile (== '\t') b
      if BS.null b'
        then await >>= go1
        else go0 b'

example2 = runEffect $ each [ "___\t___\t\t___\t\t\t___" ]
                       >-> convertTabs
                       >-> printAll
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32157114

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档