一个sed题
- vinoca
- 帖子: 59
- 注册时间: 2011-03-21 18:30
- tangboyun
- 帖子: 701
- 注册时间: 2009-07-25 1:57
- 联系:
Re: 一个sed题
提供几个恶心的测试用例:
a b c d ea b c d ea b c d e ea
ea ea ea
ea ea ea
ea b ea b ea
b ea b ea b ea
应该输出:
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea ea空ea
ea ea空ea
ea b ea空b空ea
b空ea b ea空b空ea
我sed水平不行,用haskell写了个。假设项里不会再嵌套空格,且遇到奇数ea执行,偶数不执行。该替换的空格用汉字’空‘显示。主要是split这块写了很多无法简化。
[haskell]
{-# LANGUAGE BangPatterns #-}
module Main where
import Data.List
import System.Environment
splitEveryEA :: String -> [String]
splitEveryEA str | "ea " `isPrefixOf` str = "" : go [] [] str
| otherwise = go [] [] str
where
go :: String -> [String] -> String -> [String]
go !acc !lss [] = lss ++ [acc]
go !acc !lss " ea" = lss ++ [acc++" "] ++ ["ea"]
go !acc !lss (x:xs) | " ea " `isPrefixOf` xs
= go [] (lss ++ [acc ++ [x] ++ " "]) (tail xs)
| otherwise
= go (acc ++ [x]) lss xs
main :: IO ()
main = do
fmap head getArgs >>= readFile >>=
\content ->
sequence_ [putStrLn $ concat $
zipWith ($) f (splitEveryEA l) | l <- lines content]
where
f = cycle [spaceToTab,id]
spaceToTab [] = []
spaceToTab (x:xs) | x == ' ' = '空' : spaceToTab xs
| otherwise = x:spaceToTab xs
[/haskell]
a b c d ea b c d ea b c d e ea
ea ea ea
ea ea ea
ea b ea b ea
b ea b ea b ea
应该输出:
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea ea空ea
ea ea空ea
ea b ea空b空ea
b空ea b ea空b空ea
我sed水平不行,用haskell写了个。假设项里不会再嵌套空格,且遇到奇数ea执行,偶数不执行。该替换的空格用汉字’空‘显示。主要是split这块写了很多无法简化。
[haskell]
{-# LANGUAGE BangPatterns #-}
module Main where
import Data.List
import System.Environment
splitEveryEA :: String -> [String]
splitEveryEA str | "ea " `isPrefixOf` str = "" : go [] [] str
| otherwise = go [] [] str
where
go :: String -> [String] -> String -> [String]
go !acc !lss [] = lss ++ [acc]
go !acc !lss " ea" = lss ++ [acc++" "] ++ ["ea"]
go !acc !lss (x:xs) | " ea " `isPrefixOf` xs
= go [] (lss ++ [acc ++ [x] ++ " "]) (tail xs)
| otherwise
= go (acc ++ [x]) lss xs
main :: IO ()
main = do
fmap head getArgs >>= readFile >>=
\content ->
sequence_ [putStrLn $ concat $
zipWith ($) f (splitEveryEA l) | l <- lines content]
where
f = cycle [spaceToTab,id]
spaceToTab [] = []
spaceToTab (x:xs) | x == ' ' = '空' : spaceToTab xs
| otherwise = x:spaceToTab xs
[/haskell]
https://github.com/tangboyun
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 一个sed题
#用X H做个华丽演习:
第一步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g;' f.txt
a b c d X b c d X b c d e X
X X X
X X X
X b X b X
b X b X b X X
第二步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g;' f.txt
a Hb Hc Hd HX b c d XH Hb Hc Hd He HX
XH HX XH
X XH HX
XH Hb HX b XH
b HX b XH Hb HX XH
第三步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g; s/ H/\t/g;' f.txt
a b c d X b c d XH b c d e X
XH X XH
X XH X
XH b X b XH
b X b XH b X XH
完成 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g; s/ H/空/g; s/X|XH/ea/g' f.txt
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea空ea ea
ea ea空ea
ea空b空ea b ea
b空ea b ea空b空ea ea
第一步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g;' f.txt
a b c d X b c d X b c d e X
X X X
X X X
X b X b X
b X b X b X X
第二步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g;' f.txt
a Hb Hc Hd HX b c d XH Hb Hc Hd He HX
XH HX XH
X XH HX
XH Hb HX b XH
b HX b XH Hb HX XH
第三步 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g; s/ H/\t/g;' f.txt
a b c d X b c d XH b c d e X
XH X XH
X XH X
XH b X b XH
b X b XH b X XH
完成 sed -r ':a;N;$!ba; s/\bea\b|$/X/g; s/X[^X]*X| /&H/g; s/ H/空/g; s/X|XH/ea/g' f.txt
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea空ea ea
ea ea空ea
ea空b空ea b ea
b空ea b ea空b空ea ea
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 一个sed题
第一和第二行如果一连三个ea,必有 空 的,因为跨行匹配。应该输出:
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea ea空ea
ea ea空ea
ea b ea空b空ea
b空ea b ea空b空ea
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 一个sed题
#实用写法:
cat f.txt
a b c d ea b c d ea b c d e ea
ea ea ea
ea ea ea
ea b ea b ea
b ea b ea b ea
sed -r ':a;N;$!ba; s/\bea\b|$/&\x1a/g; s/\x1a[^\x1a]*\x1a| /&\x1b/g; s/ \x1b/空/g; s/\x1a|\x1b//g' f.txt
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea空ea ea
ea ea空ea
ea空b空ea b ea
b空ea b ea空b空ea
cat file.txt
a b c d ea b c d ea b c d e
a b c d ea b c d ea b c d eabc ea jh
a b c
a b c d ea b c d ea b c d e
a b c d ea b c d b c d e
sed -r ':a;N;$!ba; s/\bea\b|$/&\x1a/g; s/\x1a[^\x1a]*\x1a| /&\x1b/g; s/ \x1b/空/g; s/\x1a|\x1b//g' file.txt
a空b空c空d空ea b c d ea空b空c空d空e
a空b空c空d空ea b c d ea空b空c空d空eabc空ea jh
a b c
a b c d ea空b空c空d空ea b c d e
a b c d ea空b空c空d空b空c空d空e
cat f.txt
a b c d ea b c d ea b c d e ea
ea ea ea
ea ea ea
ea b ea b ea
b ea b ea b ea
sed -r ':a;N;$!ba; s/\bea\b|$/&\x1a/g; s/\x1a[^\x1a]*\x1a| /&\x1b/g; s/ \x1b/空/g; s/\x1a|\x1b//g' f.txt
a空b空c空d空ea b c d ea空b空c空d空e空ea
ea空ea ea
ea ea空ea
ea空b空ea b ea
b空ea b ea空b空ea
cat file.txt
a b c d ea b c d ea b c d e
a b c d ea b c d ea b c d eabc ea jh
a b c
a b c d ea b c d ea b c d e
a b c d ea b c d b c d e
sed -r ':a;N;$!ba; s/\bea\b|$/&\x1a/g; s/\x1a[^\x1a]*\x1a| /&\x1b/g; s/ \x1b/空/g; s/\x1a|\x1b//g' file.txt
a空b空c空d空ea b c d ea空b空c空d空e
a空b空c空d空ea b c d ea空b空c空d空eabc空ea jh
a b c
a b c d ea空b空c空d空ea b c d e
a b c d ea空b空c空d空b空c空d空e
上次由 fnan 在 2011-11-30 18:00,总共编辑 1 次。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
- eexpress
- 帖子: 58428
- 注册时间: 2005-08-14 21:55
- 来自: 长沙
- tangboyun
- 帖子: 701
- 注册时间: 2009-07-25 1:57
- 联系:
Re: 一个sed题
额,我要补语文了,我以为楼主的是要每行分开考虑。sed这玩意儿我开man看半天还是累,不是经常用的话用法容易忘呀。 

https://github.com/tangboyun
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。
-
- 帖子: 61
- 注册时间: 2010-04-29 22:00
- 系统: Gentoo Linux ~amd64
- 联系:
Re: 一个sed题
[haskell]
f b (' ':xs) = (if b then '空' else ' '):f b xs
f b ('e':'a':xs) = 'e':'a':f (not b) xs
f b (x:xs) = x:f b xs
f b "" = ""
main = interact $ unlines . map (f True) . lines
[/haskell]
f b (' ':xs) = (if b then '空' else ' '):f b xs
f b ('e':'a':xs) = 'e':'a':f (not b) xs
f b (x:xs) = x:f b xs
f b "" = ""
main = interact $ unlines . map (f True) . lines
[/haskell]
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
- tangboyun
- 帖子: 701
- 注册时间: 2009-07-25 1:57
- 联系:
Re: 一个sed题
这个interact用的很棒也,不过split的处理无法区分包含字母ea的项,恶心在split上,haskell里调正则不如脚本方便。MaskRay 写了:[haskell]
f b (' ':xs) = (if b then '空' else ' '):f b xs
f b ('e':'a':xs) = 'e':'a':f (not b) xs
f b (x:xs) = x:f b xs
f b "" = ""
main = interact $ unlines . map (f True) . lines
[/haskell]
https://github.com/tangboyun
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。
http://tangboyun.is-programmer.com/
提问的智慧————Eric Steven Raymond
回答的智慧————Andrew Clarke
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。
急急急标题什么的,最讨厌了!
急急复急急,急急何其多,我生待急急,万事急急急。