如何在嵌入在 bash 脚本中的 sed 脚本中转义反斜杠

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

How do I escape backslashes in a sed script embedded in a bash script

bashsedescaping

提问by hauptmech

I want to edit a file via a sed script in a bash script. I want this to be easy to maintain later; easy to understand and modify. The replacement string looks like:

我想通过 bash 脚本中的 sed 脚本编辑文件。我希望这在以后易于维护;易于理解和修改。替换字符串如下所示:

PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'

In a perfect world, it would like this:

在一个完美的世界里,它会是这样的:

sed -i "s/^PS1.*$/PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'/g" /etc/skel/.bashrc

The problem is that bash and sed are stripping out the \giving the following result in the file:

问题是 bash 和 sed 正在删除\文件中给出的以下结果:

PS1='[e[1;32m][@h W]$[e[0m]'

Obviously single quotes can't be used. A brute force solution is to use escapes, but for this to work I get a really ugly looking line:

显然不能使用单引号。一个蛮力的解决方案是使用转义,但为了这个工作,我得到了一条非常难看的线:

sed -i "s/^PS1.*$/PS1='\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\]'/g" /etc/skel/.bashrc

I want the script to be readable and self contained (not using external files). Any alternatives to the above?

我希望脚本可读且自包含(不使用外部文件)。有没有以上的替代方案?

采纳答案by hauptmech

Bash's printf can add the necessary escapes, leaving the string to be inserted in an readable, editable form.

Bash 的 printf 可以添加必要的转义,让字符串以可读、可编辑的形式插入。

sed -i "s/^PS1.*$/$(printf "%q" "PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'")/g" /etc/skel/.bashrc

Not trying to stick it all on one line makes the whole thing clearer.

不试图将所有内容都放在一条线上会使整个事情变得更加清晰。

REPL=$(printf "%q" "PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'")
sed -i "s/^PS1.*$/$REPL/g" /etc/skel/.bashrc

回答by potong

This might work for you:

这可能对你有用:

echo "PS1=abc" |
sed 's/^PS1.*$/PS1='\''\[\e[1;32m\][\u@\h \W]\$\[\e[0m\]'\''/'
PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'

回答by Spencer Rathbun

How about this:

这个怎么样:

sed -i 's/^PS1.*$/PS1=SINGLEQUOTESLASH[SLASHe[1;32mSLASH][SLASHu@SLASHh SLASHW]SLASH$SLASH[SLASHe[0mSLASH]SINGLEQUOTE/g' /etc/skel/.bashrc
sed -i "s/SINGLEQUOTE/'/g" /etc/skel/.bashrc
sed -i "s/SLASH/\/g" /etc/skel/.bashrc

Doing it in two passes is less efficient, but a few more microseconds is unnoticeable to most people.

分两次执行效率较低,但大多数人不会注意到多几微秒。

回答by thiton

Use a sed script file with sed -f. This alternative is not pretty, too, because it means having an additional file lying around, but at least you avoid shell escapes.

将 sed 脚本文件与sed -f. 这个替代方案也不是很好,因为它意味着有一个额外的文件存在,但至少你可以避免 shell 转义。