Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
add comment

4 Answers

sed -i "/^version =/s/'[^']*'/'NEW_VERSION_IS_HERE'/" your_file
share|improve this answer
    
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 '12 at 21:57
    
@robintw Works for me. Did you copy/paste it wrong? –  tylerl Mar 28 '12 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 '12 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 '12 at 20:57
add comment

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'
share|improve this answer
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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