Заменить целую строку в файле из командной строки

Заменить целую строку в файле из командной строки

У меня есть текстовый файл, содержимое которого похоже на это:

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

Я хотел бы заменить version = '0.5'строку на, version = Xгде X — аргумент командной строки, переданный скрипту, а затем сделать то же самое для release =строки.

Есть ли простая команда, которую я могу вызвать для выполнения такого рода замены? Я немного погуглил sed, но, похоже, глобальная подстановка в sed потребует от меня поиска version = '0.5', но все, что я действительно хочу найти, это строку, начинающуюся с version =- поскольку я понятия не имею, какая версия может быть, когда я запускаю скрипт!

Есть идеи?

решение1

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

решение2

Один из способов использования perl:

Предположим, что infileв нем есть содержимое, которое вы вставили в свой вопрос.

Содержание 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], $_; 
}

Запустите его так:

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

Со следующим выводом:

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

решение3

Если $Xэто параметр, в котором хранится новая версия,

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

Предполагается, что $Xимеет разумное значение, например 1.2.3-foo, и не содержит символов, которые являются специальными для edинтерпретатора команд.

решение4

В качестве скрипта оболочки:

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

Это всего лишь быстрый пример. Он не проверяет ошибки и не создает резервную копию исходного файла в случае, если одно из перенаправлений вывода удалит его и оставит вас с пустым файлом. Я говорю, что не используйте это в производстве, но это даст вам представление о том, как сделать то, что вы пытаетесь сделать.

Связанный контент