Replace text with equal length using sed

Is there a way to replace the pattern with the equal length of somethings else (e.g. dots, zeros, etc.) using sed? Like this:

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

("I" requires a newer version of sed to ignore the case)
It was easy: a word starting with "sh" is replaced by double dots (..), but how to do it is something like this: ... sells sea ...... by the sea .....

Any idea? Hooray!

+6
source share
6 answers

This may work for you (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 

In essence; it copies a word starting with sh or sh , replaces each character . , and then again inserts a new line into the original. When all occurrences of the search string are exhausted, it displays the string.

+2
source

My suspicion is that you cannot do this in standard sed , but you can do it with Perl or something else with more powerful regex processing.

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

The e modifier means that the replacement pattern is executed by a Perl script; in this case, it repeats the character . as many times as there are characters in the matched pattern. Modifier g repeats through the line; the i modifier is case insensitive. The -p option to Perl prints each line after processing in the script specified by the -e option, a replacement command.

+6
source

Does this awk-oneliner do the job for you?

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

check your details:

 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 ..... 
+5
source
 $ 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 ..... 
+4
source

Old question, but I found a nice and repetitive short one-line solution:

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

It works by replacing one character at a time in a loop.

:a; run the loop

s/\([Ss]h\.*\)[^\. ] s/\([Ss]h\.*\)[^\. ] find sh followed by any number . (our completed work so far), followed by a non-point or spatial symbol (which we are going to replace)

/\1./; replace it with our completed work so far plus one more . .

ta; if we made any replacement cycle, otherwise ...

s/[Ss]h/../g replace sh with two . and call it day.

+3
source

As others have noted, sed is not suitable for this task. This, of course, is possible, here is one example that works on separate lines with spaces separated by spaces:

 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' 

Output:

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

The first "sed" replaces the spaces with newlines, the second with a period, the third removes the newlines as shown in this answer .

If you have unpredictable word separators and / or paragraphs, this approach will soon become unmanageable.

Edit - Multiline Alternatives

Here's one way to handle multi-line input inspired by Kent's comments (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' 

Output:

 ... 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 ..... 
+2
source

All Articles