diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Simon Marechal
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Simon Marechal nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Text/Regex/PCRE/ByteString/Utils.hs b/Text/Regex/PCRE/ByteString/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/PCRE/ByteString/Utils.hs
@@ -0,0 +1,129 @@
+module Text.Regex.PCRE.ByteString.Utils
+    ( substitute
+    , split
+    , substituteCompile
+    , splitCompile
+    ) where
+
+import Text.Regex.PCRE.ByteString
+import qualified Data.ByteString.Char8 as BS
+import Control.Monad.Error
+import qualified Data.Vector as V
+import Data.Attoparsec.ByteString.Char8
+import Control.Applicative
+
+{-| Substitutes values matched by a `Regex`. References can be used.
+
+It doesn't support anything else than global substitution for now ..
+-}
+substitute :: Regex             -- ^ The regular expression, taken from a call to `compile`
+           -> BS.ByteString     -- ^ The source string
+           -> BS.ByteString     -- ^ The replacement string
+           -> IO (Either String BS.ByteString)
+substitute regexp srcstring repla = runErrorT $ do
+    let check x = case x of
+                      Right y -> return y
+                      Left rr -> throwError rr
+    parsedReplacement <- check (parseOnly repparser repla)
+    (matches, captures) <- getMatches regexp srcstring V.empty
+    let !replaceString = applyCaptures parsedReplacement captures
+        applyReplacement :: RegexpSplit BS.ByteString -> BS.ByteString
+        applyReplacement (Unmatched x) = x
+        applyReplacement (Matched _) = replaceString
+    return $! BS.concat $! map applyReplacement matches
+
+-- Transforms the parsed replacement and the vector of captured stuff into
+-- the destination ByteString.
+applyCaptures :: [Replacement] -> V.Vector BS.ByteString -> BS.ByteString
+applyCaptures repl capt = BS.concat (map applyCaptures' repl)
+    where
+        applyCaptures' :: Replacement -> BS.ByteString
+        applyCaptures' (RawReplacement r) = r
+        applyCaptures' (IndexedReplacement idx) = if V.length capt < idx
+                                                      then ""
+                                                      else capt V.! (idx-1)
+
+-- | Splits strings, using a `Regex` as delimiter.
+split :: Regex  -- ^ The regular expression, taken from a call to `compile`
+      -> BS.ByteString -- ^ The source string
+      -> IO (Either String [BS.ByteString])
+split regexp srcstring = fmap (either Left (Right . removeEmptyLeft . regexpUnmatched . fst)) $ runErrorT (getMatches regexp srcstring V.empty)
+    where
+        removeEmptyLeft = reverse . dropWhile BS.null . reverse
+
+data RegexpSplit a = Matched a
+                   | Unmatched a
+                   deriving (Show, Eq, Ord)
+
+instance Functor RegexpSplit where
+    fmap f (Matched x)   = Matched (f x)
+    fmap f (Unmatched x) = Unmatched (f x)
+
+regexpAll :: [RegexpSplit a] -> [a]
+regexpAll = map unreg
+    where
+        unreg ( Matched x   ) = x
+        unreg ( Unmatched x ) = x
+
+isMatched :: RegexpSplit a -> Bool
+isMatched (Matched _) = True
+isMatched _ = False
+
+regexpUnmatched :: [RegexpSplit a] -> [a]
+regexpUnmatched = regexpAll . filter (not . isMatched)
+
+getMatches :: Regex -> BS.ByteString -> V.Vector BS.ByteString -> ErrorT String IO ([RegexpSplit BS.ByteString], V.Vector BS.ByteString)
+getMatches _ "" curcaptures  = return ([], curcaptures)
+getMatches creg src curcaptures = do
+    x <- liftIO $ regexec creg src
+    case x of
+        Left (rcode, rerror) -> throwError ("Regexp application error: " ++ rerror ++ "(" ++ show rcode ++ ")")
+        Right Nothing -> return ([Unmatched src], curcaptures)
+
+        -- Now this is a trick, I don't know exactly why this happens, but this happens with empty regexps. We are going to cheat here
+        Right (Just ("","",rm,_)) -> return (map (Unmatched . BS.singleton) (BS.unpack rm), curcaptures)
+
+        Right (Just (before,current,remaining,captures)) -> do
+            (remain, nextcaptures) <- getMatches creg remaining (curcaptures V.++ (V.fromList captures))
+            return (Unmatched before : Matched current : remain, nextcaptures)
+
+
+data Replacement = RawReplacement BS.ByteString
+                 | IndexedReplacement Int
+                 deriving (Show)
+
+repparser :: Parser [Replacement]
+repparser = many replacement <* endOfInput
+
+replacement :: Parser Replacement
+replacement = fmap RawReplacement rawData <|> escapedThing
+
+rawData :: Parser BS.ByteString
+rawData = takeWhile1 (/= '\\')
+
+escapedThing :: Parser Replacement
+escapedThing = do
+    void (char '\\')
+    fmap IndexedReplacement decimal <|> fmap (RawReplacement . BS.cons '\\') rawData
+
+
+-- | Compiles the regular expression (using default options) and `substitute`s
+substituteCompile :: BS.ByteString     -- ^ The regular expression
+                  -> BS.ByteString     -- ^ The source string
+                  -> BS.ByteString     -- ^ The replacement string
+                  -> IO (Either String BS.ByteString)
+substituteCompile regexp srcstring repla = do
+    re <- compile compBlank execBlank regexp
+    case re of
+        Right cre -> substitute cre srcstring repla
+        Left rr   -> return $ Left $ "Regexp compilation failed: " ++ show rr
+
+-- | Compiles the regular expression (using default options) and `split`s.
+splitCompile :: BS.ByteString -- ^ The regular expression
+             -> BS.ByteString -- ^ The source string
+             -> IO (Either String [BS.ByteString])
+splitCompile regexp srcstring = do
+    re <- compile compBlank execBlank regexp
+    case re of
+        Right cre -> split cre srcstring
+        Left rr   -> return $ Left $ "Regexp compilation failed: " ++ show rr
diff --git a/pcre-utils.cabal b/pcre-utils.cabal
new file mode 100644
--- /dev/null
+++ b/pcre-utils.cabal
@@ -0,0 +1,45 @@
+-- Initial pcre-utils.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                pcre-utils
+version:             0.1.0.0
+synopsis:            Perl-like substitute and split for PCRE regexps.
+description:         This package introduces split and replace like functions using PCRE regexps.
+license:             BSD3
+license-file:        LICENSE
+author:              Simon Marechal
+maintainer:          bartavelle@gmail.com
+-- copyright:           
+category:            Text
+build-type:          Simple
+cabal-version:       >=1.8
+
+source-repository head
+  type: git
+  location: git://github.com/bartavelle/pcre-utils.git
+
+
+library
+  exposed-modules:     Text.Regex.PCRE.ByteString.Utils
+  -- other-modules:       
+  ghc-options:         -Wall
+  ghc-prof-options:    -caf-all -auto-all
+  extensions:          OverloadedStrings, BangPatterns
+  build-depends:       base ==4.6.*, regex-pcre-builtin, bytestring, attoparsec, mtl, vector
+
+Test-Suite test-split
+    hs-source-dirs: test
+    type:           exitcode-stdio-1.0
+    ghc-options:    -Wall
+    extensions:     OverloadedStrings
+    build-depends:  base,pcre-utils,HUnit,bytestring, regex-pcre-builtin
+    main-is:        split.hs
+
+Test-Suite test-subs
+    hs-source-dirs: test
+    type:           exitcode-stdio-1.0
+    ghc-options:    -Wall
+    extensions:     OverloadedStrings
+    build-depends:  base,pcre-utils,HUnit,bytestring, regex-pcre-builtin
+    main-is:        subs.hs
+
diff --git a/test/split.hs b/test/split.hs
new file mode 100644
--- /dev/null
+++ b/test/split.hs
@@ -0,0 +1,39 @@
+module Main where
+
+import Test.HUnit
+import Text.Regex.PCRE.ByteString
+import Text.Regex.PCRE.ByteString.Utils
+import qualified Data.ByteString as BS
+
+tests :: [(BS.ByteString, BS.ByteString, [BS.ByteString])]
+tests = [ ("a"   , "lala"       , ["l","l"])
+        , ("l"   , "lala"       , ["", "a", "a"])
+        , ("x"   , "lala"       , ["lala"])
+        , ("[la]", "lalaz"      , ["", "", "", "", "z"])
+        , ("[la]", "lalazoula"  , ["", "", "", "", "zou"])
+        , ("[la]", "lalazoulaz" , ["", "", "", "", "zou", "", "z"])
+        , ("[la]", "lala"       , [])
+        , ("l"   , "l\nl"       , ["", "\n"])
+        , (""    , "abc"        , ["a", "b", "c"])
+        , ("(ha)", "lahachac"      , ["la","c","c"])
+        ]
+
+toTest :: (BS.ByteString, BS.ByteString, [BS.ByteString]) -> IO Test
+toTest cas@(regexp, string, result) = do
+    let failtest :: String -> IO Test
+        failtest rr = return $ TestCase $ assertFailure $ rr ++ " " ++ show cas
+    x <- compile compBlank execBlank regexp
+    case x of
+        Left  rr -> failtest ("Failure when compiling regexp: " ++ show rr)
+        Right rregexp -> do
+            res <- split rregexp string
+            case res of
+                Right rs -> return (rs ~?= result)
+                Left err -> failtest ("Could not split regexp: " ++ err)
+
+main :: IO ()
+main = do
+    (Counts _ _ e f) <- fmap TestList (mapM toTest tests) >>= runTestTT
+    if (e > 0) || (f > 0)
+        then error "Tests failed"
+        else return ()
diff --git a/test/subs.hs b/test/subs.hs
new file mode 100644
--- /dev/null
+++ b/test/subs.hs
@@ -0,0 +1,31 @@
+module Main where
+
+import Test.HUnit
+import Text.Regex.PCRE.ByteString
+import Text.Regex.PCRE.ByteString.Utils
+import qualified Data.ByteString as BS
+
+tests :: [(BS.ByteString, BS.ByteString, BS.ByteString, BS.ByteString)]
+tests = [ ("l", "x", "lap\\nin", "xap\\nin")
+        , ("log(\\d+)truc", "x\\1x", "log186truc", "x186x")
+        ]
+
+toTest :: (BS.ByteString, BS.ByteString, BS.ByteString, BS.ByteString) -> IO Test
+toTest cas@(regexp, replacement, string, result) = do
+    let failtest :: String -> IO Test
+        failtest rr = return $ TestCase $ assertFailure $ rr ++ " " ++ show cas
+    x <- compile compBlank execBlank regexp
+    case x of
+        Left  rr -> failtest ("Failure when compiling regexp: " ++ show rr)
+        Right rregexp -> do
+            res <- substitute rregexp string replacement
+            case res of
+                Right rs -> return (rs ~?= result)
+                Left err -> failtest ("Could not split regexp: " ++ err)
+
+main :: IO ()
+main = do
+    (Counts _ _ e f) <- fmap TestList (mapM toTest tests) >>= runTestTT
+    if (e > 0) || (f > 0)
+        then error "Tests failed"
+        else return ()
