9

I have a config file with following structure.

ValueOne = 1
ValueTwo = 2
ValueThree = 3

I want a one liner bash script to find ValueTwo and change the value to 22222.

Any idea? Not School Thing

8

I bet there'll be better ones but here's my go:

If the config file has parameters on their own line

sed -i '/ValueTwo/s/= .*/= 22222/' config_file
  • /ValueTwo/ : Search for the string ValueTwo to find which line to operate on (Addresses)
  • s/= .*/= 22222/ : On the lines that match the search above, substitute = .* for = 22222 (Substitute)
  • = .* : Search for the = character followed by a space () character followed by 0 or more of any character (.*) (Regex example)
  • = 22222 : Replace what's found with the literal string = 22222

This will replace the contents of config_file in-place. To create a new file with the parameter changed, remove -i and place > new_file at the end of the line.


If your config file has parameters on the same line (like the unedited question):

sed -i 's/ValueTwo = [^ ]*/ValueTwo = 22222/' config_file

This will replace the contents of config_file in-place as well. It will work as long as there are no spaces in the parameter for ValueTwo. This will also work in the case where parameters are on their own line, but the former method is perhaps more robust in that case.

| improve this answer | |
  • 6
    I think you lost your bet. – mikeserv Sep 9 '14 at 16:05
  • 1
    That is some RegEx'ish mumbo jumbo, would love an explanation /s/=? – Ray Foss May 17 '16 at 14:16
  • 1
    @RayFoss I made an edit to the answer to add an explanation of the Regex with links to the docs – gene_wood Dec 29 '18 at 18:53
2
perl -p -i.bak -e 's/ValueTwo = 2/ValueTwo = 22222/' path/to/configfile

will edit the file in-place and save a copy of the original in case of finger trouble. You can do the same with awk.

| improve this answer | |
1

Assuming ValueTwo is a number, sed will do just fine:

sed -e 's/ValueTwo = [0-9]*/ValueTwo = 2222/g' your_config_file > output_file
| improve this answer | |
  • +1 but why would you limit it to numbers? What's wrong with .*? – terdon Jul 16 '14 at 14:12
  • @terdon, in the first version of the question all variables were in one line, separated by whitespaces. Also it is a good practice to limit the scope of regular expression to values that you expect to find - this way you can filter out some unexpected errors - e.g. when a text is logged instead of a number. – Paweł Rumian Jul 16 '14 at 14:21
1

I'd go for awk:

awk '/ValueTwo/{$3=22222}1;' file > newfile

The above checks whether a given line matches ValueTwo and sets the 3d field to 222 on matching lines. The 1; is just an awk shgorthand way of writing print $0, it will print each line. Since it is outside the match block (/ValueTwo/{}), it will cause all lines to be printed.

Since you asked for a bash solution though (don't know why you would prefer one but still), you could try this:

while read key eq val; do
    [ $key = "ValueTwo" ] && val=22222
    printf "%s %s %s\n" $key $eq $val
done <  file
| improve this answer | |
0

Using ex editor (part of Vi):

ex +'%s/^ValueTwo[^=]\?=[^0-9]\?\zs[^$]\+/22222/' -scwq config.ini

Explanation:

  • +cmd - executes ex/vi command;
  • %s/foo/bar/ - search and replace syntax;
  • ^ - beginning of the line;
  • [^=]\?=[^0-9]\? - selects area around equal character (=);
  • \zs[^$] - selects part for the replacement till end of the line;
  • /22222/ - pattern to replace to (everything after \zs);
  • -s - silent mode;
  • -c<command> - executes <command>;
  • -cwq - executes write and quit;
| improve this answer | |

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.