用sedreplace同等长度的文本

有没有一种方法可以用sedreplace与其他东西(例如点,零等)相等长度的图案? 喜欢这个:

maci:/ san$ echo "She sells sea shells by the sea shore" | sed 's/\(sh[az]*\)/../gI' .. sells sea .. by the sea .. 

“我”需要较新版本的sed忽略大小写
这很容易:以“sh”开头的单词被双点代替(..),但是我怎么能这样做: ... sells sea ...... by the sea .....

任何想法? 干杯!

Solutions Collecting From Web of "用sedreplace同等长度的文本"

这可能适用于你(GNU sed):

 sed -r ':a;/\b[Ss]h\S+/!b;s//\n&\n/;h;s/.*\n(.*)\n.*/\1/;s/././g;G;s/(.*)\n(.*)\n.*\n/\2\1/;ta' file 

在本质上; 它复制以shSh开头的单词,用每个字符替换. 然后重新插入新的字符串到原来的。 当搜索字符串的所有出现已经耗尽时,它将打印出该行。

我的怀疑是你不能用标准的sed来做,但是你可以用Perl或其他更强大的正则表达式处理。

 $ echo "She sells sea shells by the sea shore" | > perl -pe 's/(sh[az]*)/"." x length($1)/gei' ... sells sea ...... by the sea ..... $ 

e修饰符表示替换模式是可执行的Perl脚本; 在这种情况下,它会重复这个字符. 与匹配模式中的字符一样多。 g修饰符在整行上重复; i修改器是用于不区分大小写的匹配。 Perl的-p选项在-e选项 – substitute命令指定的脚本中处理后打印每行。

这个awk-oneliner为你做这个工作吗?

 awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1' file 

测试你的数据:

 kent$ echo "She sells sea shells by the sea shore"|awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1' ... sells sea ...... by the sea ..... 
 $ echo "She sells sea shells by the sea shore" | awk '{ head = "" tail = $0 while ( match(tolower(tail),/sh[az]*/) ) { dots = sprintf("%*s",RLENGTH,"") gsub(/ /,".",dots) head = head substr(tail,1,RSTART-1) dots tail = substr(tail,RSTART+RLENGTH) } print head tail }' ... sells sea ...... by the sea ..... 

正如其他人所指出的那样,sed并不适合这项任务。 当然有可能,下面是一个以空格分隔的单词作为单行的例子:

 echo "She sells sea shells by the sea shore" | sed 's/ /\n/g' | sed '/^[Ss]h/ s/[^[:punct:]]/./g' | sed ':a;N;$!ba;s/\n/ /g' 

输出:

 ... sells sea ...... by the sea ..... 

第一个“sed”用换行符替换空格,第二个是点,第三个删除换行符,如此答案中所示 。

如果你有不可预测的单词分隔符和/或段落,这种方法很快变得难以管理。

编辑 – 多行替代

Kent的评论(GNU sed)的启发下,这是处理多行输入的一种方法:

 echo " She sells sea shells by the sea shore She sells sea shells by the sea shore, She sells sea shells by the sea shore She sells sea shells by the sea shore She sells sea shells by the sea shore She sells sea shells by the sea shore " | # Add a \0 to the end of the line and surround punctuations and whitespace by \n sed 's/$/\x00/; s/[[:punct:][:space:]]/\n&\n/g' | # Replace the matched word by dots sed '/^[Ss]h.*/ s/[^\x00]/./g' | # Join lines that were separated by the first sed sed ':a;/\x00/!{N;ba}; s/\n//g' 

输出:

 ... sells sea ...... by the sea ..... ... sells sea ...... by the sea ....., ... sells sea ...... by the sea ..... ... sells sea ...... by the sea ..... ... sells sea ...... by the sea ..... ... sells sea ...... by the sea ..... 

一个古老的问题,但我发现一个不错的和相当短的一行sed解决方案:

 sed ':a;s/\([Ss]h\.*\)[^\. ]/\1./;ta;s/[Ss]h/../g' 

通过在循环中一次替换一个字符来工作。

:a; 开始一个循环

s/\([Ss]h\.*\)[^\. ] s/\([Ss]h\.*\)[^\. ]搜索一个sh后跟任意数量的. (我们迄今完成的工作),然后是非点或空格字符(我们将要替换的)

/\1./; 取而代之的是我们迄今完成的工作再加上另一个.

ta; 如果我们做了任何替代,循环,否则…

s/[Ss]h/../g用两个替换sh . 并称之为一天。