string 为 sed 替换模式转义字符串

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

Escape a string for a sed replace pattern

stringsedescaping

提问by Alexander Gladysh

In my bash script I have an external (received from user) string, which I should use in sed pattern.

在我的 bash 脚本中,我有一个外部(从用户接收)字符串,我应该在 sed 模式中使用它。

REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"

How can I escape the $REPLACEstring so it would be safely accepted by sedas a literal replacement?

我怎样才能转义$REPLACE字符串,以便它被安全地接受sed为字面替换?

NOTE:The KEYWORDis a dumb substring with no matches etc. It is not supplied by user.

注意:KEYWORD是一个没有匹配等的哑子字符串。它不是由用户提供的。

采纳答案by Pianosaurus

Warning: This does notconsider newlines. For a more in-depth answer, see this SO-questioninstead. (Thanks, Ed Morton & Niklas Peter)

警告:这并没有考虑换行。有关更深入的答案,请参阅此 SO-question。(谢谢,埃德·莫顿和尼克拉斯·彼得)

Note that escaping everything is a bad idea. Sed needs many characters to be escaped to gettheir special meaning. For example, if you escape a digit in the replacement string, it will turn in to a backreference.

请注意,逃避一切是一个坏主意。Sed 需要对许多字符进行转义以获得它们的特殊含义。例如,如果您对替换字符串中的数字进行转义,它将变成反向引用。

As Ben Blank said, there are only three characters that need to be escaped in the replacement string (escapes themselves, forward slash for end of statement and & for replace all):

正如 Ben Blank 所说,在替换字符串中只有三个字符需要转义(转义自己,正斜杠表示语句结束,& 表示全部替换):

ESCAPED_REPLACE=$(echo $REPLACE | sed -e 's/[\/&]/\&/g')
# Now you can use ESCAPED_REPLACE in the original sed statement
sed "s/KEYWORD/$ESCAPED_REPLACE/g"

If you ever need to escape the KEYWORDstring, the following is the one you need:

如果您需要转义KEYWORD字符串,以下是您需要的:

sed -e 's/[]\/$*.^[]/\&/g'

And can be used by:

并可用于:

KEYWORD="The Keyword You Need";
ESCAPED_KEYWORD=$(echo $KEYWORD | sed -e 's/[]\/$*.^[]/\&/g');

# Now you can use it inside the original sed statement to replace text
sed "s/$ESCAPED_KEYWORD/$ESCAPED_REPLACE/g"

Remember, if you use a character other than /as delimiter, you need replace the slash in the expressions above wih the character you are using. See PeterJCLaw's comment for explanation.

请记住,如果您使用的字符不是/分隔符,则需要将上述表达式中的斜杠替换为您正在使用的字符。有关解释,请参阅 PeterJCLaw 的评论。

Edited:Due to some corner cases previously not accounted for, the commands above have changed several times. Check the edit history for details.

编辑:由于以前没有考虑到一些极端情况,上面的命令已经更改了几次。检查编辑历史以获取详细信息。

回答by scre_www

The sed command allows you to use other characters instead of /as separator:

sed 命令允许您使用其他字符代替/分隔符:

sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'

The double quotes are not a problem.

双引号不是问题。

回答by Ben Blank

The only three literal characters which are treated specially in the replace clause are /(to close the clause), \(to escape characters, backreference, &c.), and &(to include the match in the replacement). Therefore, all you need to do is escape those three characters:

在替换子句中被特殊处理的仅有三个文字字符是/(关闭子句)、\(转义字符、反向引用、&c.)和&(在替换中包含匹配项)。因此,您需要做的就是转义这三个字符:

sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\/\\/g; s/\//\\//g; s/&/\\&/g')/g"

Example:

例子:

$ export REPLACE="'\"|\/><&!"
$ echo fooKEYWORDbar | sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\/\\/g; s/\//\\//g; s/&/\\&/g')/g"
foo'"|\/><&!bar

回答by Gurpartap Singh

Based on Pianosaurus's regular expressions, I made a bash function that escapes both keyword and replacement.

基于 Pianosaurus 的正则表达式,我做了一个 bash 函数,可以同时转义关键字和替换。

function sedeasy {
  sed -i "s/$(echo  | sed -e 's/\([[\/.*]\|\]\)/\&/g')/$(echo  | sed -e 's/[\/&]/\&/g')/g" 
}

Here's how you use it:

以下是您如何使用它:

sedeasy "include /etc/nginx/conf.d/*" "include /apps/*/conf/nginx.conf" /etc/nginx/nginx.conf

回答by user2460464

It's a bit late to respond... but there IS a much simpler way to do this. Just change the delimiter (i.e., the character that separates fields). So, instead of s/foo/bar/you write s|bar|foo.

回复有点晚了……但是有一种更简单的方法可以做到这一点。只需更改分隔符(即分隔字段的字符)。所以,而不是s/foo/bar/你写s|bar|foo.

And, here's the easy way to do this:

而且,这是执行此操作的简单方法:

sed 's|/\*!50017 DEFINER=`snafu`@`localhost`\*/||g'

The resulting output is devoid of that nasty DEFINER clause.

结果输出没有那个讨厌的 DEFINER 子句。

回答by destenson

It turns out you're asking the wrong question. I also asked the wrong question. The reason it's wrong is the beginning of the first sentence: "In my bashscript...".

事实证明你问错了问题。我也问错了问题。错误的原因是第一句话的开头:“在我的bash脚本中...”。

I had the same question & made the same mistake. If you're using bash, you don't need to use sed to do string replacements (and it's muchcleaner to use the replace feature built into bash).

我有同样的问题并犯了同样的错误。如果您使用的是 bash,则不需要使用 sed 来进行字符串替换(使用 bash 内置的替换功能更简洁)。

Instead of something like, for example:

而不是类似的东西,例如:

function escape-all-funny-characters() { UNKNOWN_CODE_THAT_ANSWERS_THE_QUESTION_YOU_ASKED; }
INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A="$(escape-all-funny-characters 'KEYWORD')"
B="$(escape-all-funny-characters '<funny characters here>')"
OUTPUT="$(sed "s/$A/$B/g" <<<"$INPUT")"

you can use bash features exclusively:

您可以专门使用 bash 功能:

INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A='KEYWORD'
B='<funny characters here>'
OUTPUT="${INPUT//"$A"/"$B"}"

回答by greggster

Use awk - it is cleaner:

使用 awk - 它更干净:

$ awk -v R='//addr:\file' '{ sub("THIS", R, 
ls | awk '{ print "awk " "'"'"'"  " {print ,,} " "'"'"'"  " "  ".old_ext > "  ".new_ext"  }' > for_the_birds
); print
function sedeasy_improved {
    sed -i "s/$(
        echo "" | sed -e 's/\([[\/.*]\|\]\)/\&/g' 
            | sed -e 's:\t:\t:g'
    )/$(
        echo "" | sed -e 's/[\/&]/\&/g' 
            | sed -e 's:\t:\t:g'
    )/g" ""
}
}' <<< "http://file:\_THIS_/path/to/a/file\is\\a\ nightmare" http://file:\_//addr:\file_/path/to/a/file\is\\a\ nightmare

回答by Alex

Here is an example of an AWK I used a while ago. It is an AWK that prints new AWKS. AWK and SED being similar it may be a good template.

这是我不久前使用的 AWK 的示例。它是一个打印新 AWKS 的 AWK。AWK 和 SED 相似,它可能是一个很好的模板。

* = \x2a
( = \x28
) = \x29

" = \x22
/ = \x2f
\ = \x5c

' = \x27
? = \x3f
% = \x25
^ = \x5e

It looks excessive, but somehow that combination of quotes works to keep the ' printed as literals. Then if I remember correctly the vaiables are just surrounded with quotes like this: "$1". Try it, let me know how it works with SED.

它看起来过分了,但不知何故,引号的组合可以将 ' 打印为文字。然后,如果我没记错的话,变量只是用这样的引号包围:“$1”。试试吧,让我知道它是如何与 SED 一起工作的。

回答by Francisco De Zuviria

I have an improvement over the sedeasy function, which WILL break with special characters like tab.

我对 sedeasy 功能进行了改进,该功能会因制表符等特殊字符而中断。

##代码##

So, whats different? $1and $2wrapped in quotes to avoid shell expansions and preserve tabs or double spaces.

那么,有什么不同呢?$1$2用引号括起来以避免外壳扩展并保留制表符或双空格。

Additional piping | sed -e 's:\t:\\t:g'(I like :as token) which transforms a tab in \t.

附加管道| sed -e 's:\t:\\t:g'(我喜欢:作为标记),它在\t.

回答by Ark25

These are the escape codes that I've found:

这些是我发现的转义码:

##代码##