1

I'm searching for a way to replace the first occurrence of a certain text in a text file with a value ${A} and the second occurrence of the same text, on a different line, with ${B}. Can this be achieved with sed or awk or any other UNIX tool?

The toolset is fairly limited: bash, common UNIX tools like sed, grep, awk etc. Perl, Python, Ruby etc. cannot be used...

Thanks in advance for any advice Robert

Example:

...
Text
Text
Text
Text
TEXT_TO_BE_REPLACED
Text
Text
Text
TEXT_TO_BE_REPLACED
Text
Text
Text
...

should be replaced with

...
Text
Text
Text
Text
REPLACEMENT_TEXT_A
Text
Text
Text
REPLACEMENT_TEXT_B
Text
Text
Text
...
Robert Petermeier
  • 4,122
  • 4
  • 29
  • 37

6 Answers6

3

Sed with one run:


sed -e 's/\(TEXT_TO_BE_REPLACED\)/REPLACEMENT_TEXT_A/1' \
    -e 's/\(TEXT_TO_BE_REPLACED\)/REPLACEMENT_B/1' &lt input_file > output_file
tmg
  • 872
  • 6
  • 7
  • I have a problem that is oposite of this. I have `\title{A64L}` and `\textbf{A64L}` in two different lines. I want to `\title{\hypertarget{A64L}{A64L}}` `\textbf{\hyperlink{A64l}{A64L}}` – alhelal Jan 01 '18 at 17:02
2

Just run your script twice - once to replace the first occurrence with ${A}, once to replace the (now first) occurence with ${B}. To replace just one occurence:

sed '0,/RE/s//to_that/' file

(shamelessly stolen from How to use sed to replace only the first occurrence in a file?)

Community
  • 1
  • 1
Frank Schmitt
  • 30,195
  • 12
  • 73
  • 107
1

Here is a possible solution using awk:

#!/usr/bin/awk -f

/TEXT_TO_BE_REPLACED/ {
   if ( n == 0 ) {
      sub( /TEXT_TO_BE_REPLACED/, "REPLACEMENT_TEXT_A", $0 );
      n++;
   }
   else if ( n == 1 ) {
      sub( /TEXT_TO_BE_REPLACED/, "REPLACEMENT_TEXT_B", $0 );
      n++;
   }
}

{
   print
}
Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110
  • This will replace all subsequent occurrences of replaceme with secondreplace (the 2nd, the 3rd, ...) - you need to add a n++ in the else if ... clause, as well. – Frank Schmitt Apr 08 '11 at 17:58
  • @Frank: I added that almost immediately after posting it. You must have been viewing the original text. Thanks for looking at it. – Mark Wilkins Apr 08 '11 at 18:06
  • Thanks for that. I had to accept Frank's answer, though, on the basis that it's shorter and I'm more comfortable with sed. – Robert Petermeier Apr 08 '11 at 18:09
0
awk 'BEGIN { a[0]="REPLACEMENT_A"; a[1]="REPLACEMENT_B"; } \
  /TEXT_TO_BE_REPLACED/ { gsub( "TEXT_TO_BE_REPLACED", a[i++]); i%=2 }; 1'
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • that will not stop after the 2nd replacement. Do you want `/TEXT_TO_BE_REPLACED/ && i<2 {gsub( "TEXT_TO_BE_REPLACED", a[i++])}` ? – glenn jackman Apr 09 '11 at 00:01
  • @glenn No, I interpreted the question to alternate the replacements. It's not clear what the desired behavior is for 3rd and higher occurrences of the text to be replaced. – William Pursell Apr 09 '11 at 01:42
0

So, you can use sed to do this like so:

First, I made a file named test.txt that contained:

well here is an example text example
and here is another example text

I choose to use the word "example" to be the value to change.

Here is the command: cat test.txt | sed -e 's/(example)/test2/2' -e 's/(example)/test1/1'

which provides the following output:

well here is an test1 text test2
and here is another test1 text

Now the sed command broken down:

s - begins search + replace 
/ - start search ended with another /
The parentheses group our text ie example
/test2/ what we are putting in place of example
The number after the slashes is the occurrence we want to replace. 

the -e allows you to run both commands on one command line.
gymnodemi
  • 61
  • 1
0

You may also use the text editor ed:

# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s file
   H
   /TEXT_TO_BE_REPLACED/s//REPLACEMENT_TEXT_A/
   /TEXT_TO_BE_REPLACED/s//REPLACEMENT_TEXT_B/
   wq
EOF
tilo
  • 1