экранировать зарезервированные символы из параметра регулярного выражения (sed) - PullRequest
3 голосов
/ 04 июля 2011

Я хочу написать скрипт, который изменяет переменную в файле .properties. Пользователь вводит новое значение, которое в свою очередь записывается в файл.

read -p "Input Variable?" newVar
sed -r 's/^\s*myvar=.*/myvar=${newVar}/' ./config.properties

К сожалению, проблемы возникают, когда пользователь вводит специальные символы. В моем случае использования весьма вероятно, что напечатан символ "/". Итак, я предполагаю, что я должен проанализировать $ {newVar} для всех слэшей и избежать их? Но как? Есть ли лучший способ?

Ответы [ 4 ]

3 голосов
/ 04 июля 2011

взгляните на bash printf

%q  quote the argument in a way that can be reused as shell input

Пример:

$ printf "%q" "input with special characters // \\ / \ $ # @"
input\ with\ special\ characters\ //\ \\\ /\ \\\ \$\ #\ @
1 голос
/ 04 июля 2011

Избегайте цитирования оболочки - это хороший общий принцип.

#! /usr/bin/env perl

use strict;
use warnings;

die "Usage: $0 properties-file ..\n" unless @ARGV;

print "New value for myvar?\n";
chomp(my $new = <STDIN>);

$^I = ".bak";
while (<>) {
  s/^(\s*myvar\s*=\s*).*$/$1$new/;
  print;
}

Замена на s///, как указано выше, знакома sed пользователям.

Приведенный выше код использует PerlПоместите средство редактирования (чаще всего включается с помощью переключателя -i, но выше с помощью специальной переменной $^I), чтобы изменять файлы, названные в командной строке, и создавать резервные копии с расширением .bak.

Пример использования:

$ cat foo.properties 
theirvar=123
myvar=FIXME

$ ./prog foo.properties 
New value for myvar?
foo\bar

$ cat foo.properties
theirvar=123
myvar=foo\bar

$ cat foo.properties.bak 
theirvar=123
myvar=FIXME
0 голосов
/ 04 июля 2011

Вам лучше использовать инструмент, который понимает переменные - Perl, может быть, AWK - пытаясь заключить в кавычки случайную строку, чтобы избежать всех непреднамеренных взаимодействий с синтаксическим анализом команды sed, что вызывает проблемы.

Такжевы не получите интерполяцию вашей переменной при использовании одинарных кавычек, и даже при -r sed не использует синтаксис Perl для регулярных выражений - -r возвращает вас только к версии egrep регулярных выражений, поэтому \s не делаетделайте то, что вы хотите.

В любом случае, игнорируя мой собственный совет, вот как мы делали это в старые времена, когда у нас не было этих лучших инструментов:

read -p "Input Variable?" newVar
sed "/^ *myvar=/c\\
myvar=`echo \"$newVar\" | sed 's/\\\\/\\\\\\\\/'`" ./config.properties

Если вы неНе думайте, что ваши пользователи поймут, как вводить буквальную обратную косую черту по вашему запросу, вы можете упростить это до:

read -p "Input Variable?" newVar
sed "/^ *myvar=/c\\
myvar=$newVar" ./config.properties
0 голосов
/ 04 июля 2011

Редактировать: упс, мы указываем только значение, а не регулярное выражение.Так что это то, что вам нужно

Вам лучше использовать perl вместо sed для этого, если оно доступно.

read -p "Input Variable?" newVar
perl -i -p -e 'BEGIN{$val=shift;}'           \
           -e 's/^\s*myvar=.*/myvar=$val/'   \
           "$newVar" ./config.properties

Edit2: Извините, по-прежнему не обрабатывает \символы в newVar.Угадай, одно из других решений лучше.Как указывалось выше, ваша проблема заключается в экранировании оболочки.

...