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

发布于 2024-12-23 16:55:25 字数 606 浏览 2 评论 0原文

我想通过 bash 脚本中的 sed 脚本编辑文件。我希望这个以后易于维护;易于理解和修改。替换字符串看起来像:

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

在完美的世界中,它会像这样:

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

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

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

显然单引号不能用过的。一个强力的解决方案是使用转义,但为了实现这一点,我得到了一条看起来非常难看的线:

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

我希望脚本可读且自包含(不使用外部文件)。除了上述之外还有其他选择吗?

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:

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:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情归归情 2024-12-30 16:55:25

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

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

不要试图将所有内容都写在一行上,这样整个事情就更清晰了。

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

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

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
成熟的代价 2024-12-30 16:55:25

这可能对你有用:

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

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\]'
兔姬 2024-12-30 16:55:25

通过 sed -f 使用 sed 脚本文件。这种替代方案也不太漂亮,因为它意味着有一个额外的文件存在,但至少可以避免 shell 转义。

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.

超可爱的懒熊 2024-12-30 16:55:25

怎么样:

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

分两遍执行的效率较低,但多几微秒对于大多数人来说是不会注意到的。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文