Хламидомонада / Говнокод #29250 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 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

Текст UNIX-way утилиты fed
Капча: p2ux

Запостил: CHayT CHayT, (Updated )

Комментарии (2) RSS

  • seo-post: по мотивом вчерашнего срача. Утилита, аналогичная sed "s/pituh/kurochka/".
    Вчерашний прототип содержал ошибку, он не матчил \n. Можете смеяться. Поэтому тут я сделал оптимизацию с отбросом trailing .* вручную.
    Чинить многострочные выражения мне было лень, но это возможно. С однострочными работает как полагается:
    echo "112233" | ./fed "(22)" "(\1)"
    11(22)33

    Бесконечный стрим:
    while true; do echo -n "skibidi "; done | ./fed " skibid(.{10}).*" "\1"
    skibidii skibidi

    Естественно, ей можно фильтровать.
    Ответить
  • Круто.

    > Капча: p2ux

    Если бы выпало p8ux, было бы интереснее.
    Ответить

Добавить комментарий

Семь раз отмерь — один отрежь, guest!

    А не использовать ли нам bbcode?


    8