- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text.Lazy.IO as LIO
import GHC.IO.StdHandles
import Text.Regex.TDFA
import qualified Text.Regex.TDFA.Text.Lazy as RL
import Data.Array
import qualified Data.Text.Lazy as TL
import System.Environment
import System.Exit
import System.IO
import qualified Language.C.Syntax.Constants as CC
import Data.Char
printMatch t matches i =
let (offset, len) = matches ! i in
let offset' = fromIntegral offset in
let len' = fromIntegral len in
LIO.putStr $ TL.take len' $ TL.drop offset' t
printHead t matches =
let (offset, len) = matches ! 0 in
let offset' = fromIntegral offset in
let len' = fromIntegral len in
LIO.putStr $ TL.take offset' t
printTrail t matches =
let (offset, len) = matches ! 0 in
let offset' = fromIntegral offset in
let len' = fromIntegral len in
LIO.putStr $ TL.drop (offset' + len') t
need_capture_trail acc ".*" = (False, reverse acc)
need_capture_trail acc [] = (True, reverse acc)
need_capture_trail acc (c : rest) = need_capture_trail (c : acc) rest
getRE :: [String] -> Either String (RL.Regex, Bool, String)
getRE args =
case args of
(re_str : repl_str : _) ->
let (trail_needed, re_str') = need_capture_trail [] re_str in
let re_text = TL.pack $ CC.unescapeString re_str' in
case RL.compile defaultCompOpt defaultExecOpt re_text of
Right re ->
Right (re, trail_needed, CC.unescapeString repl_str)
Left err ->
Left err
_ ->
Left "Regexp expected"
-- replacement :: TL.Text -> Int -> _ -> String -> IO ()
replacement _ _ _ [] = return ()
replacement t n_matches matches (c : rest)
| ord c <= n_matches = do
printMatch t matches (ord c)
replacement t n_matches matches rest
| True = do
putChar c
replacement t n_matches matches rest
exitError :: String -> IO ()
exitError msg = do
hPutStrLn stderr msg
exitWith (ExitFailure 1)
main :: IO ()
main = do
args <- getArgs
case getRE args of
Right (re, trail_needed, repl) -> do
t <- LIO.hGetContents stdin
case RL.execute re t of
Right (Just matches) ->
do
let n_matches = snd $ bounds matches
-- print matches
printHead t matches
replacement t n_matches matches repl
if trail_needed then
printTrail t matches
else
return ()
Right Nothing -> do
exitError "Pattern not found"
Left err -> do
exitError err
Left err -> do
exitError err
Вчерашний прототип содержал ошибку, он не матчил \n. Можете смеяться. Поэтому тут я сделал оптимизацию с отбросом trailing .* вручную.
Чинить многострочные выражения мне было лень, но это возможно. С однострочными работает как полагается:
Бесконечный стрим:
Естественно, ей можно фильтровать.
> Капча: p2ux
Если бы выпало p8ux, было бы интереснее.