Dane Savot
Dane Savot

Reputation: 192

Add text to the end if not already added

I have the following lines:

source = "git::ssh://[email protected]/test//bar"
source = "git::ssh://[email protected]/test//foo?ref=tf12"
resource = "bar"

I want to update any lines that contain source and git words by adding ?ref:tf12 to the end of the line but inside ". If the line already contains ?ref=tf12, it should skip

source = "git::ssh://[email protected]/test//bar?ref=tf12"
source = "git::ssh://[email protected]/test//foo?ref=tf12"
resource = "bar"

I have the following expression using sed, but it outputs wrongly

sed 's#source.*git.*//.*#&?ref=tf12#' file.tf

source = "git::ssh://[email protected]/test//bar"?ref=tf12
source = "git::ssh://[email protected]/test//foo"?ref=tf12?ref=tf12
resource = "bar"

Upvotes: 1

Views: 85

Answers (2)

Jay
Jay

Reputation: 3950

sed '/?ref=tf12"/!s#\(source.*git.*//.*\)"#\1?ref=tf12"#' file.tf

/?ref=tf12"/! Only run substitude command if this pattern (?ref=tf12") doesn't match
\(...\)", \1 Instead of appending to the entire line using &, only match the line until the last ". Use parentheses to match everything before that " into a group which I can then refer with \1 in the replacement. (Where we re-add the ", so that it doesn't get lost)

Upvotes: 2

tripleee
tripleee

Reputation: 189457

Using simple regular expressions for this is rather brittle; if at all possible, using a more robust configuration file parser would probably be a better idea. If that's not possible, you might want to tighten up the regular expressions to make sure you don't modify unrelated lines. But here is a really simple solution, at least as a starting point.

sed -e '/^ *source *= *"git/!b' -e '/?ref=tf12" *$/b' -e 's/" *$/?ref=tf12"/' file.tf

This consists of three commands. Remember that sed examines one line at a time.

  • /^ * source *= *"git/!b - if this line does not begin with source="git (with optional spaces between the tokens) leave it alone. (! means "does not match" and b means "branch (to the end of this script)" i.e. skip this line and fetch the next one.)
  • /?ref=tf12" *$/b similarly says to leave alone lines which match this regex. In other words, if the line ends with ?ref=tf12" (with optional spaces after) don't modify it.
  • s/"* $/?ref=tf12"/ says to change the last double quote to include ?ref=tf12 before it. This will only happen on lines which were not skipped by the two previous commands.

Upvotes: 2

Related Questions