2

I am using Linux. I got a yml file and I want to delete this using sed :

exposureMachineSshAccess  
  username:
  password:
  whiteList:
    - mLB99
    - mLB10
  machines:
  - machineId:
    username: ''
    password: ''
  - machineId:
    username: ''
    password: ''

I've created this regex and it looks ok:

exposureMachineSshAccess:\n([ ].*\n)+

And I'm calling this :

sed -i '/exposureMachineSshAccess:\n([ ].*\n)+/d'  /home/common_config.yml
sed -i 's/exposureMachineSshAccess:/d/gm' /home/common_config.yml

If I remove the regex I got the file changed but it doesn't work the other way around. What is wrong?

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
Marcio
  • 21
  • 2
  • Possible duplicate of https://stackoverflow.com/questions/5014632/how-can-i-parse-a-yaml-file-from-a-linux-shell-script – tripleee Feb 16 '18 at 10:15

3 Answers3

4

The reason your regex doesn't work is that sed examines a single line at a time. You want to delete lines in an address range where the starting address is the exposureMachineSshAccess line and the end is the password: line.

sed -i '/exposureMachineSshAccess/,/    password:/d' common_config.yml

This is still imprecise in that it requires the password line to be the last line in this YAML record. If you have empty lines between records, use that as the ending address instead. If you have reliable indentation, maybe stop at the next line which is flush to the left margin (but this requires some refactoring of the script in order not to delete the line at the end of the range, too).

The proper solution is to use a tool which properly understands YAML. I proposed a duplicate for this question which has some vaguely promising short Python snippets which might be more precise and more robust than the chewing gum and duct tape approach, that is, attempting to handle structured file formats with just regex.

tripleee
  • 175,061
  • 34
  • 275
  • 318
2

Solution with tac and sed: Which will delete til the last occurrence of string password: in Input_file in case you don't want to do that then Solution 2nd could help you on same:

tac Input_file | sed "/    password: ''/,/exposureMachineSshAccess/d" | tac

Let's say following is the Input_file:

cat Input_file
exposureMachineSshAccess
  username:
  password:
  whiteList:
    - mLB99
    - mLB10
  machines:
  - machineId:
    username: ''
    password: ''
  - machineId:
    username: ''
    password: ''
singh is king ......
test1221

Then after running above code output will be as follows:

tac  Input_file | sed "/    password: ''/,/exposureMachineSshAccess/d" | tac
testtest1221  test
singh is king ......
test1221

Solution 2nd:

sed  "/exposureMachineSshAccess/,/    password: ''/d"   Input_file
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • 1
    This will delete from the first occurrence of `password:` anywhere in the file, not constrained to the current YAML record. – tripleee Feb 16 '18 at 10:14
  • @tripleee, sorry tripleee sir, I thought that is what OP needed, the string OP pasted(and tried to put into regex) should be deleted. Please correct me if I did something wrong, could improve it then. – RavinderSingh13 Feb 16 '18 at 10:16
  • @DOWN VOTER: Please let me know the reason of down vote here?? – RavinderSingh13 Feb 16 '18 at 10:17
  • Assume there are hundreds of records with `password:` in them but only one which starts with `exposureMachineSshAccess`. – tripleee Feb 16 '18 at 10:17
  • @tripleee, yes I kept that in mind so only I am using `tac` if OP could let me know on it that OP want only first occurrence of it then could change the code. – RavinderSingh13 Feb 16 '18 at 10:19
2

This might work for you (GNU sed):

sed '/^\S/h;G;/\nexposureMachineSshAccess/!P;d' file

This copies the section header. Appends the section header to each line and prints/deletes according to a section header match.

potong
  • 55,640
  • 6
  • 51
  • 83