转义正则表达式(sed)参数中的保留字符

3

我想编写一个脚本来修改.properties文件中的变量。用户输入新值,然后将其写入文件。

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

很不幸,当用户输入特殊字符时会出现问题。在我的使用情况下,很可能输入"/"字符。所以我猜想我需要解析${newVar}中的所有斜杠并对其进行转义?但是如何操作呢?是否有更好的方法?

4个回答

3

看一下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
问题在于,shell会在printf命令看到$newVar之前就剥离掉\字符。除了编写自定义shell循环外,我不知道有什么方法可以输出/传递包含\字符的shell变量。即使在上面的示例中,两个\字符中的一个也已经丢失了。这确实是一个棘手的问题。有人能解决吗? - Sodved

1

避免使用Shell引用是一个很好的通用原则。

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

最好使用理解变量的工具,比如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

编辑:哎呀,我们只引用值,而不是正则表达式。所以这就是你需要的。

如果可以使用,最好使用perl而不是sed

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

编辑2:抱歉,仍然无法处理newVar中的\字符。猜测其他解决方案更好。如前所述,处理shell转义是您的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接