PepeHands
PepeHands

Reputation: 1406

matching ranges in sed

In my prog I need to, using sed, replace some characters with one another one in some file. But between some words and only if this string contains some extra word. So I wrote:

sed -re '/from:/,/end/ { /extraword/s/[_old_characters_]/new_character/g; }'

But this code totaly ignors this /from:/,/end/ strings. It replaces all [_old_characters_] with new_character starting from from: and to the end of this line. What have I done wrong?

What I need is:

sed -re '/A/,/B/ { /word/s/[C]/X/g; }'

file:

word CCC A CCC B CCC
wor A CCC B

becomes:

word CCC A XXX B CCC
wor A CCC B

Upvotes: 1

Views: 108

Answers (3)

potong
potong

Reputation: 58351

This might work for you (GNU sed):

sed -r '/word/{:a;/(A)([^ABC]*C+[^ABC]*)(B)/{s//\1\n\2\n\3/;h;y/C/X/;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/;ba}}' file

This filter lines which contain the word word and A followed by C followed by B. Such lines then have markers (\n's) placed after A and before B and a copy of the line is placed in the hold space (HS). All C's are replace with X's and then the copy in the HS is appended to the amended line and the required line is rebuilt from both. The new line is then tested again and if necessary the procedure is repeated.

If A and B are words then use the same technique but substitute \n after A and before B first, then test for /\n.*C.*\n/ remembering to remove all \n's if the condition is not met.

Upvotes: 2

Nick Russo
Nick Russo

Reputation: 1542

In case using sed proves too ugly, here's a Perl solution:

$ perl -pe 'if (m/word/) {s/(A[^C]*) (.*) ([^C]*B)/$1 . " " . "X" x length($2) . " " . $3/gei;}'
word CCC A CCC B CCC
word CCC A XXX B CCC
wor A CCC B
wor A CCC B

Upvotes: 1

nu11p01n73R
nu11p01n73R

Reputation: 26667

Something like

sed '/^word/s/A CCC B/A XXX B/g'

eg

>>> echo word CCC A CCC B CCC | sed '/^word/s/A CCC B/A XXX B/g'
word CCC A XXX B CCC

Upvotes: 0

Related Questions