I need to change the numerical value of a variable stored in a text file from the command line.I've tried to script it with Bash, but only got so far:#!/bin/bashclearvim The_Generator.c(This is hopefully where I modify the The_Generator.c file).-c 'wq'
Changing a numerical value in a file with Vim from a script
shell script;text processing;vim
Vim isn't the best way to get this done, but it is possible:$ vim -c '%s/^\(VARIABLE=\)\d\+/\13/' -c wq The_Generator.c%s means search and replace globally in Vi. The search pattern looks for a line beginning with VARIABLE= followed by one or more digits (\d+), then it replaces the digit(s) with 3, the new value of the variable I've chosen for the sake of the example here. The VARIABLE= part is put back into the line with the \1 backreference.There are several weaknesses here that make this suboptimal:Vim is a fairly heavy program for a simple task like this. Notice that you get a brief flash of the full-screen vi interface while doing this. That's wasteful; we can do better.Vim isn't as widely deployed as the alternatives below, and we're using at least three features of Vim that aren't likely to exist in more traditional flavors of Vi such as Berkeley nvi or Solaris vi: backreferences, \d in regexes, and multiple -c flags.Because Vim isn't geared to this sort of problem, we need the explicit save and exit option here (-c wq) which is more briefly expressed in the alternatives below.A more efficient and more portable option is to use sed:$ sed -i -e 's/^\(VARIABLE=\)[0-9][0-9]*/\13/' The_Generator.cIf you're on a system where you can use POSIX extended regular expressions in sed via -E, you can make the command shorter than the Vim equivalent:$ sed -E -i -e 's/^(VARIABLE=)[0-9]+/\13/' The_Generator.cThat let us drop several backslashes and express the one or more digits bit more compactly.If efficiency isn't paramount, you can get more expressive power with the Perl pie idiom:$ perl -pi -e 's/^(VARIABLE=)\d+/${1}3/' The_Generator.cIt's shorter than the sed -E alternative because Perl regexes are even more powerful than POSIX extended REs.The largest difference here is in the way Perl handles backreferences. You normally give them as $NUM syntax instead of \DIGIT, but we put the number in curly brackets here to separate it from the replacement text, since it is also a number. Without the brackets, Perl would go looking for backreference #13, find no matching text and thus fail to do what you want.Some people like Awk for this sort of thing, but I was unable to come up with an expression that pulled its own weight by being shorter than the sed option while being faster than the Perl option.