Abhinav Dhiman
Abhinav Dhiman

Reputation: 755

Replacing a string with newline character with another string

I have a huge file containing datasets such as:

100  S|||
100  S|d1|||88|||
100  S|0d|f6||f630|589f||

I need to replace ||| with |||||||, only if the line contains no more pipes other than a single ||| sequence.

I tried using sed command for this requirement:

sed -i 's/|||/|||||||/g' input.txt

However, it is changing records in second line as well, which is not intended.

What would be the correct command usage? Any help will be highly appreciated.

Upvotes: 1

Views: 51

Answers (3)

potong
potong

Reputation: 58351

This might work for you (GNU sed):

sed '/^[^|]*|||[^|]*$/s/|||/&&|/' file

If a line only contains 3 consecutive |'s, replace them by 7 |'s.

Upvotes: 0

RavinderSingh13
RavinderSingh13

Reputation: 133428

With awk, you could try following. Written and tested with shown samples in GNU awk.

awk 'gsub(/\|/,"&")==3{gsub(/\|\|\|/,"&||||")} 1' Input_file

Explanation: Adding detailed explanation for above.

awk '                       ##Starting awk program from here.
gsub(/\|/,"&")==3{          ##checking if line has only 3 ||| then do following.
  gsub(/\|\|\|/,"&||||")    ##Globally substituting ||| with itself and |||| here.
}
1                           ##printing current line here.
' Input_file                ##Mentioning Input_file name here.

Upvotes: 1

anubhava
anubhava

Reputation: 784898

You can use this sed command with capture groups to match non-pi[e characters before and after |||:

sed -E 's/^([^|]*)(\|\|\|)([^|]*)$/\1\2||||\3/' file

100  S|||||||
100  S|d1|||88|||
100  S|0d|f6||f630|589f||

Details:

  • ^: Start
  • ([^|]*): Match 0 or more non-pipe characters in capture group #1
  • (\|\|\|): Match 3 pipe characters in capture group #2
  • ([^|]*): Match 0 or more non-pipe characters in capture group #3
  • $: End
  • \1\2||||\3 is replacement pattern that inserts |||| after back-reference #2 i.e. \2 while putting back \1 and \3 as is.

Upvotes: 2

Related Questions