Reemplazar toda la línea en un archivo desde la línea de comandos

Reemplazar toda la línea en un archivo desde la línea de comandos

Tengo un archivo de texto que tiene un contenido similar a este:

# 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'

Me gustaría reemplazar la version = '0.5'línea version = Xdonde X es un argumento de línea de comando dado a un script y luego hacer lo mismo con la release =línea.

¿Existe algún comando simple al que pueda llamar para realizar este tipo de reemplazo? Lo he investigado sedun poco, pero parece que la sustitución global en sed requeriría que buscara version = '0.5', pero todo lo que realmente quiero buscar es una línea que comience con version =, ya que no tengo idea de cuál podría ser la versión cuando ejecuta el script!

¿Algunas ideas?

Respuesta1

sed -i "/^version =/s/'[^']*'/'NEW_VERSION_IS_HERE'/" your_file

Respuesta2

Una forma usando perl:

Suponiendo que infiletenga contenido que haya pegado en su pregunta.

Contenido de 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], $_; 
}

Ejecútelo como:

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

Con la siguiente salida:

# 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'

Respuesta3

Si $Xes el parámetro donde se almacena la nueva versión,

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

Esto supone $Xque tiene un valor razonable, como 1.2.3-fooy que no hay caracteres especiales para el edintérprete de comandos.

Respuesta4

Como script de shell:

#!/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

Este es sólo un ejemplo rápido. No realiza ninguna verificación de errores y no realiza una copia de seguridad del archivo original en el caso de que una de las redirecciones de salida lo borre y lo deje con un archivo vacío. Lo que estoy diciendo es que no uses esto en producción, pero te dará una idea de cómo hacer lo que estás intentando hacer.

información relacionada