bash 如何将包含斜杠的变量传递给 sed

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27787536/
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-08 21:49:08  来源:igfitidea点击:

How to pass a variable containing slashes to sed

bashsed

提问by buydadip

How do you pass a variable containing slashes as a pattern to sed?

如何将包含斜杠的变量作为模式传递给sed

For example, if I have the following variable:

例如,如果我有以下变量:

var="/Users/Documents/name/file"

I want to pass it to sedas so:

我想将它传递给sed

sed "s/$var/replace/g" "$file"

However I get errors. How can I circumvent the issue?

但是我得到错误。我怎样才能规避这个问题?

回答by anubhava

Use an alternate regex delimiter as sedallows you to use any delimiter (including control characters):

使用备用正则表达式分隔符,因为sed允许您使用任何分隔符(包括控制字符):

sed "s~$var~replace~g" $file

回答by glenn Hymanman

A pure bash answer: use parameter expansionto backslash-escape any slashes in the variable:

一个纯粹的 bash 答案:使用参数扩展来反斜杠转义变量中的任何斜杠:

var="/Users/Documents/name/file"
sed "s/${var//\//\/}/replace/g" $file

回答by buydadip

Another way of doing it, although uglier than anubhava's answer, is by escaping all the backslashes in varusing another sedcommand:

另一种方法,虽然比 anubhava 的答案更丑陋,是通过var使用另一个sed命令转义所有反斜杠:

var=$(echo "$var" | sed 's/\//\\//g')

then, this will work:

然后,这将起作用:

sed "s/$var/replace/g" $file

回答by repzero

Using /in sed as a delimiter will conflict with the slashes in the variable when substituted and as a result you will get an error. One way to circumvent this is to use another delimiter that is unique from any characters that is in that variable.

使用/in sed 作为分隔符将在替换时与变量中的斜杠冲突,因此您将收到错误消息。规避此问题的一种方法是使用另一个分隔符,该分隔符与该变量中的任何字符都是唯一的。

var="/Users/Documents/name/file"

you can use the octothorpe character which suits the occasion (or any other character that is not a /for ease of use)

您可以使用适合场合的 octothorpe 字符(或任何其他不/便于使用的字符)

sed "s#$var#replace#g" 

or

或者

sed 's#$'$var'#replace#g'

this is suitable when the variable does not contain spaces

这适用于变量不包含空格的情况

or

或者

sed 's#$"'$var'"#replace#g'

It is wiser to use the above since we are interested in substituting whatever is in that variable only as compared to double quoting the whole command which can cause your shell to interpet any character that might be considered a special shell character to the shell.

使用上述更明智,因为与双引号整个命令相比,我们只对替换该变量中的任何内容感兴趣,这可能导致您的 shell 将任何可能被视为特殊 shell 字符的字符插入到 shell。

回答by tripleee

This is an old question, but none of the answers here discuss operations other than s/from/to/in much detail.

这是一个古老的问题,但这里的答案除了s/from/to/详细讨论操作之外,都没有讨论。

The general form of a sedstatement is

sed语句的一般形式是

*address* *action*

where addresscan be a regex range or a line number range (or empty, in which case the actionis applied to every input line). So for example

其中address可以是正则表达式范围或行号范围(或为空,在这种情况下,该操作适用于每个输入行)。所以例如

sed '1,4d' file

will delete lines 1 through 4 (the addressis the line number range 1,4and the actionis the ddelete command); and

将删除第 1 到 4 行(地址是行号范围1,4动作d删除命令);和

sed '/ick/,$s/foo/bar/' file

will replace the first occurrence of foowith baron any line between the first match on the regex ickand the end of the file (the addressis the range /ick/,$and the actionis the ssubstitute command s/foo/bar/).

将在正则表达式的第一个匹配项和文件末尾之间的任何行上替换第一次出现的foowith (地址是范围,动作是替代命令)。barick/ick/,$ss/foo/bar/

In this context, if ickcame from a variable, you could do

在这种情况下,如果ick来自一个变量,你可以做

sed "/$variable/,$s/foo/bar/"

(notice the use of double quotes instead of single, so that the shell can interpolate the variable, and the necessity to quote the literal dollar sign inside double quotes) but if the variable contains a slash, you will get a syntax error. (The shell expands the variable, then passes the resulting string to sed; so sedonly sees literal text - it has no concept of the shell's variables.)

(注意使用双引号而不是单引号,以便 shell 可以插入变量,并且需要在双引号内引用文字美元符号)但是如果变量包含斜杠,您将收到语法错误。(shell 扩展变量,然后将结果字符串传递给sed; 所以sed只能看到文字——它没有 shell 变量的概念。)

The cure is to use a different delimiter (where obviously you need to be able to use a character which cannot occur in the variable's value), but unlike in the s%foo%bar%case, you also need a backslash before the delimiter if you want to use a different delimiter than the default /:

解决方法是使用不同的分隔符(显然你需要能够使用一个不能出现在变量值中的字符),但与这种s%foo%bar%情况不同的是,如果你想使用不同的分隔符,你还需要在分隔符前加一个反斜杠分隔符比默认值/

sed "\%$variable%,$s/foo/bar/" file

(inside single quotes, a single backslash would obviously suffice); or you can separately escape every slash in the value. This particular syntax is Bash only:

(在单引号内,一个反斜杠显然就足够了);或者您可以单独转义值中的每个斜杠。此特定语法仅适用于 Bash:

sed "/${variable//\//\/}/,$s/foo/bar/" file

or if you use a different shell, try

或者如果您使用不同的外壳,请尝试

escaped=$(echo "$variable" | sed 's%/%\/%g')
sed "s/$escaped/,$s/foo/bar/" file

For clarity, if $variablecontained the string 1/2then the above commands would be equivalent to

为清楚起见,如果$variable包含字符串,1/2则上述命令等效于

sed '\%1/2%,$s/foo/bar/' file

in the first case, and

在第一种情况下,和

sed '/1\/2/,$s/foo/bar/' file

in the second.

在第二。

回答by choroba

Use Perl, where variables are first class citizens, not just expanding macros:

使用 Perl,其中变量是一等公民,而不仅仅是扩展宏:

var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
  • -preads the input line by line and prints the line after processing
  • \Qquotes all the metacharacters in the following string (not needed for the value presented here, but necessary if the value contained [or some other values special for regular expresisons)
  • -p逐行读取输入并在处理后打印该行
  • \Q引用以下字符串中的所有元字符(此处显示的值不需要,但如果包含的值[或其他一些对正则表达式特殊的值是必需的)