2

I have the following values in a config.yml file:

scratch-org-def: config/project-scratch-def.json
assign-permset: false
permset-name: 
run-apex-tests: true
apex-test-format: tap
delete-scratch-org: false
show-scratch-org-url: true

I need to replace all occurrences of dashes (-) to the left of the colon (:) with underscores (_).

I've tried sed '/.*: /s/-/_/g' config.yml but it replaces all dashes (including the config/project-scratch-def.json).

I've tried sed '/^[^:]*:/s/-/_/g' config.yml, hoping to stop at the colon, but it does the same.

  • is it mandatory to perform the replacement namely in sed? – RomanPerekhrest Feb 10 '18 at 17:17
3
$ awk '{ gsub("-", "_", $1) } 1' FS=':' OFS=':' config.yml
scratch_org_def: config/project-scratch-def.json
assign_permset: false
permset_name:
run_apex_tests: true
apex_test_format: tap
delete_scratch_org: false
show_scratch_org_url: true

This awk script reads the file as a :-delimited set of fields. It applies gsub() to the first field on each line, changing every dash to an underscore. The lone 1 is short for { print } which will print each (now modified) input line.

FS=':' OFS=':' sets the input and output field separators to :.

It may be possible to do this with sed as well, either through some very complicated regular expression or by utilizing its hold-space (or both), but that's not a solution that "rolls off the tongue".


(after some thinking) Using sed:

$ sed 'h;s/^[^:]*//;x;s/:.*$//;y/-/_/;G;s/\n//' config.yml
scratch_org_def: config/project-scratch-def.json
assign_permset: false
permset_name:
run_apex_tests: true
apex_test_format: tap
delete_scratch_org: false
show_scratch_org_url: true

Explanation of each step:

  1. h: Copy the pattern-space (the current input line) to the hold-space (a "general purpose" buffer).
  2. s/^[^:]*//: Remove everything before the first : in the pattern-space.
  3. x: Swap the hold-space and the pattern-space.
  4. s/:.*$//: Remove the : and everything after it in the pattern-space.

    The pattern-space now contains the unmodified left-hand side of the :, while the hold-space contains the unmodified right-hand side, including the :.

  5. y/-/_/: Change all dashes to underscores in the pattern-space.

  6. G: Append the hold-space to the end of the pattern-space with a newline between the two.
  7. s/\n//: Remove that newline character from the previous step.
  8. (Implicit p): Print the pattern-space to standard output.

Steps 4 and 5 may be interchanged without any change in result.

In short: sed is not (may not be) the right tool for the job.

3

I think you can do it in sed by replacing dashes in a loop, breaking out once everything up to the first colon contains no dashes:

sed ':a; /^[^-:]*:/b; s/-/_/;ta'

Ex.

$ sed ':a; /^[^-:]*:/b; s/-/_/;ta' config.xml 
scratch_org_def: config/project-scratch-def.json
assign_permset: false
permset_name: 
run_apex_tests: true
apex_test_format: tap
delete_scratch_org: false
show_scratch_org_url: true
  • So, as soon as there are no dashes (or colons, is this needed? yes it is, for lines with multiple colons) before the first colon, the script prints the line and continues with the next. If there are, the first dash is substituted and the script branches back to the beginning... Yes, that ought to work. – Kusalananda Feb 10 '18 at 23:40
  • It would be interesting to do some benchmarks on our solutions. I might get around to do that tomorrow... – Kusalananda Feb 10 '18 at 23:47
  • When using GNU sed, our solutions are of similar time complexity. Under OpenBSD sed, mine is about 20% faster. Also, under OpenBSD sed, the command line has to be divided up into sed -e ':a;/^[^-:]*:/b' -e 's/-/_/;ta' as the b instruction otherwise would generate an error ("undefined label ''"). – Kusalananda Feb 11 '18 at 10:37
0

I Achieved the results in 3 steps

First i have seperated second part after colon saved in Second_part.txt file

Second steps i have seperated first part till colon and replaced "- " with "_" and saved in file first_part_after_relacement

Final step using paste command i joined two files so achieved required result

Commands

sed -ne "s/\(.*:\)\(.*\)/\2/p" l.txt > Second_part.txt
sed -ne "s/\(.*:\)\(.*\)/\1/p" l.txt | sed "s/-/_/g" > first_part_after_relacement
paste first_part_after_relacement Second_part.txt | sed  -r "s/\s+//g"

Output

scratch_org_def:config/project-scratch-def.json
assign_permset:false
permset_name:
run_apex_tests:true
apex_test_format:tap
delete_scratch_org:false
show_scratch_org_url:true

Note: 2 steps are more when compared to earlier solution provided

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.