bash 无需正则表达式的简单搜索和替换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7970702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:01:09  来源:igfitidea点击:

Simple search and replace without regex

perlbashtext

提问by the_mandrill

I've got a file with various wildcards in it that I want to be able to substitute from a (bash) shell script. I've got the following which works great until one of the variables contains characters that are special to regexes:

我有一个包含各种通配符的文件,我希望能够从(bash)shell 脚本中替换它。在其中一个变量包含正则表达式特有的字符之前,我有以下这些工作得很好:

VERSION="1.0"
perl -i -pe "s/VERSION/${VERSION}/g" txtfile.txt   # no problems here

APP_NAME="../../path/to/myapp"
perl -i -pe "s/APP_NAME/${APP_NAME}/g" txtfile.txt  # Error!

So instead I want something that just performs a literal text replacement rather than a regex. Are there any simple one-line invocations with perl or another tool that will do this?

所以相反,我想要一些只执行文字文本替换而不是正则表达式的东西。是否有任何简单的单行调用 perl 或其他工具可以做到这一点?

采纳答案by Michael Goldshteyn

How about the following:

以下情况如何:

perl -i -pe "s|APP_NAME|\Q${APP_NAME}|g" txtfile.txt

Since a vertical bar is not a legal character as part of a path, you are good to go.

由于竖线作为路径的一部分不是合法字符,因此您可以继续使用。

回答by Borodin

The 'proper' way to do this is to escape the contents of the shell variables so that they aren't seen as special regex characters. You can do this in Perl with \Q, as in

执行此操作的“正确”方法是转义 shell 变量的内容,这样它们就不会被视为特殊的正则表达式字符。您可以在 Perl 中使用 \Q 执行此操作,如

s/APP_NAME/\Q${APP_NAME}/g

but when called from a shell script the backslash must be doubled to avoid it being lost, like so

但是当从 shell 脚本调用时,反斜杠必须加倍以避免丢失,就像这样

perl -i -pe "s/APP_NAME/\Q${APP_NAME}/g" txtfile.txt

But I suggest that it would be far easier to write the entire script in Perl

但我建议用 Perl 编写整个脚本会容易得多

回答by Jess

I don't particularly like this answer because there should be a better way to do a literal replace in perl. \Qis cryptic. Using quotemetaadds extra lines of code.

我不是特别喜欢这个答案,因为应该有更好的方法在 perl 中进行字面替换。 \Q是神秘的。Usingquotemeta添加了额外的代码行。

But... You can use substrto replace a portion of a string.

但是...您可以substr用来替换字符串的一部分。

#!/usr/bin/perl
my $name = "Jess.*";
my $sentence = "Hi, my name is Jess.*, dude.\n";
my $new_name = "Prince//";
my $name_idx = index $sentence, $name;
if ($name_idx >= 0) {
    substr ($sentence, $name_idx, length($name), $new_name ); 
}
print $sentence;

Output:

输出:

Hi, my name is Prince//, dude.

回答by glenn Hymanman

You don't have to use a regular expression for this:

您不必为此使用正则表达式:

perl -pe '
  foreach $var ("VERSION", "APP_NAME") {
    while (($i = index($_, $var)) != -1) {
      substr($_, $i, length($var)) = $ENV{$var};
    }
  }
'

Make sure you exportyour variables.

确保你export的变量。

回答by sehe

 perl -i -pe "s/APP_NAME/\Q${APP_NAME}\E/g" txtfile.txt
 perl -i -pe "s/APP_NAME/\Q${APP_NAME}\E/g" txtfile.txt

For some reason that didn't quite work as advertised. This variation does seem to work, though:

出于某种原因,这并不像宣传的那样奏效。不过,这种变化似乎确实有效:

 perl -i -pe "$r = qq/\Q${APP_NAME}\E/; s/APP_NAME/$r/go"

rationale: http://perldoc.perl.org/perlre.html#Escape-sequences

基本原理:http: //perldoc.perl.org/perlre.html#Escape-sequences

回答by codemaker

You can use a regex but escape any special characters.

您可以使用正则表达式,但要转义任何特殊字符。

Something like this may work.

像这样的事情可能会奏效。

APP_NAME="../../path/to/myapp"
APP_NAME=`echo "$APP_NAME" | sed -e '{s:/:\/:}'`
perl -i -pe "s/APP_NAME/${APP_NAME}/g" txtfile.txt

回答by Tom Fenech

I managed to get a working solution, partly based on bits and pieces from other peoples answers:

我设法得到了一个可行的解决方案,部分基于其他人的答案:

app_name='../../path/to/myapp'
perl -pe "$r = q/${app_name//\//\/}/; s/APP_NAME/$r/g" <<<'APP_NAME'

This creates a perl variable $rfrom the result of the shell parameter expansion:

$r将根据 shell 参数扩展的结果创建一个 perl 变量:

${app_name//\//\/}

${            # open parameter expansion
app_name      # variable name 
//            # start global substitution
\/            # match / (backslash-escaped to avoid being interpreted as delimiter)
/             # delimiter
\/           # replace with \/ (literal backslash needs to be escaped)
}             # close parameter expansion

All that work is needed to prevent forward slashes inside the variable from being treated as perl syntax, which would otherwise close the q//quotes around the string.

所有这些工作都是为了防止变量内的正斜杠被视为 perl 语法,否则会关闭q//字符串周围的引号。

In the replacement part, use the variable $r(the $is escaped, to prevent it from being treated as a shell variable within double quotes).

在替换部分,使用变量$r$被转义,以防止它被视为双引号内的 shell 变量)。

Testing it out:

测试一下:

$ app_name='../../path/to/myapp'
$ perl -pe "$r = q/${app_name//\//\/}/; s/APP_NAME/$r/g" <<<'APP_NAME'
../../path/to/myapp