5

I have a text file which has some contents similar to this:

# General information about the project.
project = u'Py6S'
copyright = u'2012, Robin Wilson'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.5'
# The full version, including alpha/beta/rc tags.
release = '0.5'

I would like to replace the version = '0.5' line with version = X where X is a command-line argument given to a script, and then do the same for the release = line.

Is there a simple command I can call to do this sort of replacing? I've looked into sed a bit, but it seems that the global substitution in sed would require me to search for version = '0.5', but all I really want to search for is a line beginning with version = - as I have no idea what the version might be when I run the script!

Any ideas?

4 Answers 4

4
sed -i "/^version =/s/'[^']*'/'NEW_VERSION_IS_HERE'/" your_file
4
  • Thanks for the answer! Unfortunately it gives the following error: sed: 1: "conf.py": command c expects \ followed by text - do you have any ideas?
    – robintw
    Mar 28, 2012 at 21:57
  • @robintw Works for me. Did you copy/paste it wrong?
    – tylerl
    Mar 28, 2012 at 23:08
  • The -i option to sed is non-standard and usually breaks symlinks. If you have GNU sed you almost always want to add the option to --follow-symlinks. In general, I recommend avoiding sed -i and using ed instead. Files are not streams.
    – jw013
    Mar 29, 2012 at 0:21
  • @robintw: What operating system are you using? You're probably not using GNU sed. If we knew which specific variant of see you have we could more accurately provide an answer.
    – bahamat
    Jul 26, 2012 at 20:57
3

One way using perl:

Assuming infile has content that you pasted in your question.

Content of script.pl:

use warnings;
use strict;
use Getopt::Long;

## Check arguments.
die qq[Usage: perl $0 <file> [--version=<num>] [--release=<num>]\n] unless @ARGV > 1;

my ($version, $release);

## Get value of arguments.
GetOptions(
    q[version=f] => \$version,
    q[release=f] => \$release,
) or die qq[ERROR: Bad input arguments\n];

## Sanity check.
exit 0 if ! defined $version && ! defined $release;

## Read input file line by line, and substitute values of 'version' and 'release'
## when matched.
while ( <> ) { 
    chomp;
    s/\A((?i:version)\s*=\s*')([^']+)(?=')/$1 . (defined $version ? $version : $2)/e;
    s/\A((?i:release)\s*=\s*')([^']+)(?=')/$1 . (defined $release ? $release : $2)/e;

    printf qq[%s\n], $_; 
}

Run it like:

perl script.pl infile --version=1.3 --release=2.6

With following output:

# General information about the project.
project = u'Py6S'
copyright = u'2012, Robin Wilson'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.3'
# The full version, including alpha/beta/rc tags.
release = '2.6'
2

If $X is the parameter where the new version is stored,

ed file << EOF
g/^version =/s/.*/version = '$X'/
g/^release =/s/.*/release = '$X'/
w
q
EOF

This assumes $X has a reasonable value, like 1.2.3-foo, and no characters that are special to the ed command interpreter.

0

As a shell script:

#!/bin/ksh

function usage {
    echo
    echo "Usage: $0 <file> <version> <release>"
    echo
    exit 1
}

function update_version {
    cat $file | sed -e "s/^version.*$/version = \'$version\'/" > $file.new
    mv $file.new $file
}

function update_release {
    cat $file | sed -e "s/^release.*$/release = \'$release\'/" > $file.new
    mv $file.new $file
}

file=$1
version=$2
release=$3

if [ ! -f $file ]; then
    usage
fi

if [ $# != 3 ]; then
    usage
fi

update_version
update_release

This is just a quick example. It doesn't do any error checking, and it doesn't back up the original file in the case of one of the output redirects erasing it and leaving you with an empty file. What I'm saying, is don't use this in production, but it will give you and idea of how to do what you're trying to do.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .