Brun
Brun

Reputation: 29

How to replace between symbols with sed command in bash

So I recently asked for help with a sed command for replacing the text between the first and second appearence of a symbol. This is the link to that question: How to replace text in a specific line between first appearence of a symbol and second appearence of it

Now I need something similar, replacing between the second and third appearence, and third to the end of the line

Let's say I have this text file:

aaaa:bbbb:cccc:dddd
eeee:ffff:gggg:hhhh
iiii:jjjj:kkkk:llll
sed "${lineNumber}s/:[^:]*/:${passwd}/" users.txt

What this line does is replacing between first and second ":" in a given line, so the question is how should the command be for replacing between second and third ":", and third to end of the line.

So, for example, the output for replacing between the second and third in the third line with "####" would look like this:

aaaa:bbbb:cccc:dddd
eeee:ffff:gggg:hhhh
iiii:jjjj:kkkk:####

and the code

sed "${lineNumber}s/:[^:]*/:${passwd}/" users.txt
                    ^^^^^^ I think that is what should be replaced

Upvotes: 1

Views: 1031

Answers (3)

potong
potong

Reputation: 58401

This might work for you (GNU sed):

sed ${lineNumber}'s/[^:]*/'${passwd}'/3' file

Substitute the 3rd occurrence of non-colons with the variable $passwd on the line numbered $lineNumber.

Upvotes: 1

puravidaso
puravidaso

Reputation: 1223

You can always use ruby which can do what sed/awk/grep can do and what they cannot do, so you do not have to carry different tools with you. In this example, you can use:

ruby -pe '$_.sub!(/(:[^:]*:)([^:]*)/, "\\1XXX")'

which means to match [a] "a colon, anything not containing a colon, another colon" and [b] "anything not containing a colon", and put back [a] (\\1) and replace [b] with XXX which is supposedly a password.

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626802

You can use

sed -E "${lineNumber} s/^(([^:]*:){2})[^:]*/\1${passwd}/"

See the online sed demo:

s='aaaa:bbbb:cccc:dddd
eeee:ffff:gggg:hhhh
iiii:jjjj:kkkk:llll'
passwd='newpass'
lineNumber=2
sed -E "${lineNumber} s/^(([^:]*:){2})[^:]*/\1${passwd}/" <<< "$s"

Output (see the text between the second and third colon on the second line):

aaaa:bbbb:cccc:dddd
eeee:ffff:newpass:hhhh
iiii:jjjj:kkkk:llll

Details

  • ^ - start of string
  • (([^:]*:){2}) - Group 1 (this value is referred to with the \1 placeholder from the regex replacement pattern): two occurrences of any chars other than : and then :
  • [^:]* - zero or more chars other than :.

Note that {2} is a range quantifier that matches its modified pattern a specified amount of times. If you change it to {3}, it will replace after the third occurrence of a : char.

Upvotes: 2

Related Questions