how to insert tab in sed command?

Viewed 90

I have a text file in which there's a YAML formatted code. Here's the code:

trigger:
  branches:
    include:
      - develop
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*

Now, I have a bash script through which I want to add a string after this string; " - develop". Here's the point I want to maintain the spacing format. Here;s my bash file code.

 $target_string= "      - develop"
 $replacment_string="      - TerraformTest/*"
 sed -i "/$target_string/a$replacment_string" test.txt

But the result I got it this:

trigger:
  branches:
    include:
      - develop
- TerraformTest/*
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*

Is there any way, I can put tab in sed command to obtain the output like this:

trigger:
  branches:
    include:
      - develop
      - TerraformTest/*
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*
5 Answers

You could use a YAML-aware tool such as yq. This command inserts TerraformTest/* as the second element in the array at .trigger.branches.include:

yq '
    .trigger.branches.include |=
        ([.[0], "TerraformTest/*", del(.[0])] | flatten)
' infile.yml 

You can match match and grab space of search string in a capture group and use it in replacement:

sed -E 's~^([[:blank:]]*)- develop~&\n\1- TerraformTest/*~' file

trigger:
  branches:
    include:
      - develop
      - TerraformTest/*
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*

Or using variables:

target_string='- develop'
replacment_string='- TerraformTest/*'

sed -E "s~^([[:blank:]]*)$target_string~&\n\1$replacment_string~" file

trigger:
  branches:
    include:
      - develop
      - TerraformTest/*
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*

Breakup:

  • ^: Start
  • ([[:blank:]]*): Match 0 or more whitespaces in capture group #1
  • $target_string: Match string contained in $target_string

Replacement:

  • &: Place whole match back
  • \n: Place a line break
  • \1: Place spaces string on next line
  • $replacment_string: Place new replacement value

TO save changes inline use:

sed -i.bak -E "s~^([[:blank:]]*)$target_string~&\n\1$replacment_string~" file

With your shown samples only, please try following awk code. Written and tested in GNU awk.

awk -v RS= '
match($0,/^trigger:\n[[:space:]]+branches:\n[[:space:]]+include:\n[[:space:]]+- develop/){
  print substr($0,RSTART,RLENGTH)"\n      - TerraformTest/*" substr($0,RSTART+RLENGTH)
}
'  Input_file

It is best practice to use a YAML aware tool such as yq, Perl, Python, etc.

Here is a Ruby:

ruby -r yaml -e 'y=YAML.load($<.read)
begin
    a=y["trigger"]["branches"]["include"]
    a.insert(a.find_index("develop")+1,"TerraformTest/*")
    puts YAML.dump(y)
rescue 
    puts "Not Found"
end
' file

Prints:

---
trigger:
  branches:
    include:
    - develop
    - TerraformTest/*
    - release/*
    - rapid/*
    - Sprint/*
    - Unity/*

Using sed

$ sed -Ei.bak '/ +- develop/{p;s/[a-z]+/TerraformTest\/*/}' file
trigger:
  branches:
    include:
      - develop
      - TerraformTest/*
      - release/*
      - rapid/*
      - Sprint/*
      - Unity/*
Related