如何将包含斜杠的变量传递给 sed
How to pass a variable containing slashes to sed
如何将包含斜杠的变量作为模式传递给 sed
?
例如,如果我有以下变量:
var="/Users/Documents/name/file"
我想这样传递给sed
:
sed "s/$var/replace/g" "$file"
但是我遇到了错误。我怎样才能避免这个问题?
使用备用正则表达式定界符,因为 sed
允许您使用任何定界符(包括控制字符):
sed "s~$var~replace~g" $file
如上所述,我们也可以使用控制字符作为分隔符,如:
sed "s^[$var^[replace^[g" file
其中 ^[
是通过同时按下 Ctrl-V-3 来输入的。
否则在 bash
shell 中,您可以使用此 sed
和 </code> 作为分隔符:</p>
<pre><code>d=$''
sed "s${d}$var${d}replace$d" file
一个纯粹的 bash 答案:使用 parameter expansion 反斜杠转义变量中的任何斜杠:
var="/Users/Documents/name/file"
sed "s/${var//\//\/}/replace/g" $file
另一种方法,虽然比 anubhava 的答案更难看,但是使用另一个 sed
命令转义 var
中的所有反斜杠:
var=$(echo "$var" | sed 's/\//\\//g')
那么,这将起作用:
sed "s/$var/replace/g" $file
在 sed 中使用 /
作为分隔符将在替换时与变量中的斜杠冲突,因此您将收到错误消息。避免这种情况的一种方法是使用另一个定界符,该定界符不同于该变量中的任何字符。
var="/Users/Documents/name/file"
您可以使用适合场合的 octothorpe 字符(或任何其他不是 /
的字符以便于使用)
sed "s#$var#replace#g"
或
sed 's#$'$var'#replace#g'
适用于变量不包含空格的情况
或
sed 's#$"'$var'"#replace#g'
使用上面的方法更明智,因为我们只对替换该变量中的任何内容感兴趣,而不是双引号整个命令,这可能导致您的 shell 插入任何可能被认为是shell.
的特殊 shell 字符
使用 Perl,其中变量首先是 class 公民,而不仅仅是扩展宏:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
逐行读取输入,处理后打印行
\Q
引用以下字符串中的所有元字符(此处显示的值不需要,但如果值包含 [
或其他一些特殊的正则表达式值则需要)
这是一个老问题,但是这里 none 的答案详细讨论了 s/from/to/
以外的操作。
sed
语句的一般形式是
*address* *action*
其中 address 可以是正则表达式范围或行号范围(或为空,在这种情况下 action 应用于每个输入线)。例如
sed '1,4d' file
将删除第 1 行到第 4 行(address 是行号范围 1,4
而 action 是 d
删除命令);和
sed '/ick/,$s/foo/bar/' file
将在正则表达式 ick
的第一个匹配项和文件结尾( 之间的任何行上用 bar
替换第一次出现的 foo
地址 是范围/ick/,$
, 动作 是s
替代命令s/foo/bar/
).
在这种情况下,如果 ick
来自变量,您可以
sed "/$variable/,$s/foo/bar/"
(注意使用双引号而不是单引号,这样 shell 可以插入变量,并且必须在双引号内引用文字美元符号)但是如果变量包含斜杠,你会得到一个语法错误。 (shell 扩展变量,然后将结果字符串传递给 sed
;因此 sed
只能看到文字文本——它没有 shell 变量的概念。)
解决方法是使用不同的分隔符(显然您需要能够使用不能出现在变量值中的字符),但与 s%foo%bar%
情况不同的是,您还需要一个反斜杠如果您想使用与默认 /
:
不同的分隔符,则在分隔符之前
sed "\%$variable%,$s/foo/bar/" file
(在单引号内,一个反斜杠显然就足够了);或者您可以单独转义值中的每个斜线。此特定语法仅 Bash:
sed "/${variable//\//\/}/,$s/foo/bar/" file
或者如果您使用不同的 shell,请尝试
escaped=$(echo "$variable" | sed 's%/%\/%g')
sed "s/$escaped/,$s/foo/bar/" file
为清楚起见,如果 $variable
包含字符串 1/2
,则上述命令等同于
sed '\%1/2%,$s/foo/bar/' file
第一种情况,
sed '/1\/2/,$s/foo/bar/' file
第二个
如何将包含斜杠的变量作为模式传递给 sed
?
例如,如果我有以下变量:
var="/Users/Documents/name/file"
我想这样传递给sed
:
sed "s/$var/replace/g" "$file"
但是我遇到了错误。我怎样才能避免这个问题?
使用备用正则表达式定界符,因为 sed
允许您使用任何定界符(包括控制字符):
sed "s~$var~replace~g" $file
如上所述,我们也可以使用控制字符作为分隔符,如:
sed "s^[$var^[replace^[g" file
其中 ^[
是通过同时按下 Ctrl-V-3 来输入的。
否则在 bash
shell 中,您可以使用此 sed
和 </code> 作为分隔符:</p>
<pre><code>d=$''
sed "s${d}$var${d}replace$d" file
一个纯粹的 bash 答案:使用 parameter expansion 反斜杠转义变量中的任何斜杠:
var="/Users/Documents/name/file"
sed "s/${var//\//\/}/replace/g" $file
另一种方法,虽然比 anubhava 的答案更难看,但是使用另一个 sed
命令转义 var
中的所有反斜杠:
var=$(echo "$var" | sed 's/\//\\//g')
那么,这将起作用:
sed "s/$var/replace/g" $file
在 sed 中使用 /
作为分隔符将在替换时与变量中的斜杠冲突,因此您将收到错误消息。避免这种情况的一种方法是使用另一个定界符,该定界符不同于该变量中的任何字符。
var="/Users/Documents/name/file"
您可以使用适合场合的 octothorpe 字符(或任何其他不是 /
的字符以便于使用)
sed "s#$var#replace#g"
或
sed 's#$'$var'#replace#g'
适用于变量不包含空格的情况
或
sed 's#$"'$var'"#replace#g'
使用上面的方法更明智,因为我们只对替换该变量中的任何内容感兴趣,而不是双引号整个命令,这可能导致您的 shell 插入任何可能被认为是shell.
的特殊 shell 字符使用 Perl,其中变量首先是 class 公民,而不仅仅是扩展宏:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
逐行读取输入,处理后打印行\Q
引用以下字符串中的所有元字符(此处显示的值不需要,但如果值包含[
或其他一些特殊的正则表达式值则需要)
这是一个老问题,但是这里 none 的答案详细讨论了 s/from/to/
以外的操作。
sed
语句的一般形式是
*address* *action*
其中 address 可以是正则表达式范围或行号范围(或为空,在这种情况下 action 应用于每个输入线)。例如
sed '1,4d' file
将删除第 1 行到第 4 行(address 是行号范围 1,4
而 action 是 d
删除命令);和
sed '/ick/,$s/foo/bar/' file
将在正则表达式 ick
的第一个匹配项和文件结尾( 之间的任何行上用 bar
替换第一次出现的 foo
地址 是范围/ick/,$
, 动作 是s
替代命令s/foo/bar/
).
在这种情况下,如果 ick
来自变量,您可以
sed "/$variable/,$s/foo/bar/"
(注意使用双引号而不是单引号,这样 shell 可以插入变量,并且必须在双引号内引用文字美元符号)但是如果变量包含斜杠,你会得到一个语法错误。 (shell 扩展变量,然后将结果字符串传递给 sed
;因此 sed
只能看到文字文本——它没有 shell 变量的概念。)
解决方法是使用不同的分隔符(显然您需要能够使用不能出现在变量值中的字符),但与 s%foo%bar%
情况不同的是,您还需要一个反斜杠如果您想使用与默认 /
:
sed "\%$variable%,$s/foo/bar/" file
(在单引号内,一个反斜杠显然就足够了);或者您可以单独转义值中的每个斜线。此特定语法仅 Bash:
sed "/${variable//\//\/}/,$s/foo/bar/" file
或者如果您使用不同的 shell,请尝试
escaped=$(echo "$variable" | sed 's%/%\/%g')
sed "s/$escaped/,$s/foo/bar/" file
为清楚起见,如果 $variable
包含字符串 1/2
,则上述命令等同于
sed '\%1/2%,$s/foo/bar/' file
第一种情况,
sed '/1\/2/,$s/foo/bar/' file
第二个