如何停止 $ / 被剥夺插入到 sed 文件中的字符串?



目标我正在尝试编写一个bash脚本来自动设置Raspbian系统。 这包括为所有用户设置自定义提示。 我需要更改/etc/bashrc 文件中的一行。

我想注释掉现有行并在其后立即添加一个新行。

所做的是,我编写了一个正确找到该行的 sed regix 命令。 它注释现有行,并紧随其后添加新行。 一切都很好,除了所有"/"$"一些文本和可能的其他重要内容都被 sed 删除了。

我已经尝试了背勾的各种组合,",括号等,但我还没有找到解决方案。

问题所在

我知道 sed 中的所有活动字符都需要分隔。 我输入了要插入在线正则表达式编辑器的行 以确保我在正确的位置有正确的斜杠来创建非活动行。

所以问题是划界完全失败了。 sed 删除了许多正则表达式类型的字符和纯文本。

代码这是测试查找/注释/插入 sed 语句的代码

#!/bin/bash
# Setup of bash prompt
# Define custom prompt
custom_prompt="  PS1='${debian_chroot:+($debian_chroot)}[e[36;40m]u[e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]\$[e[m][e[93m]>[e[m]'"
# delimited version of the prompt
sed_custom_prompt="  PS1=' ${debian_chroot:+($debian_chroot)}\[\e[36;40m\]\u\[\e[m\]\[\e[93m\]@\[\e[m\]\[\e[36m\]\h\[\e[m\]: \[\e[92m\]\w\[\e[m\] \[\e[92m\]\\$\[\e[m\]$'"

### Setup Bash Prompt
# relevant section from /etc/bashrc is:
# if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
#    PS1='${debian_chroot:+($debian_chroot)}u@h:w$ ' # this is the line I want to subsitute
# fi
#This is the desired outcome. The original line is commented out. The new line is active
# if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
#   # PS1='${debian_chroot:+($debian_chroot)}u@h:w$ ' # this is the line I want to subsitute
#    PS1='${debian_chroot:+($debian_chroot)}[e[36;40m]u[e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]\$[e[m][e[93m]>[e[m]'
# fi

# this is the test sed command that works on a test copy of bash in ~
# it comments the target line then inserts abcdef on the next line.  It works as expected.
#sed -i 's/^*PS1=.*/#&nabcdef/' ~/bash.bashrc
# I tried this command but all the back slashes and other characters were stripped off.
sed  -i 's/^*PS1=.*/#&n'"$sed_custom_prompt"'/' ~/bash.bashrc

Actual faulty file output after sed.  Note that symbols and other text is stripped off.
if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
#PS1='${debian_chroot:+($debian_chroot)}u@h:w$ '
PS1='[e[36;40m][e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]$[e[m][e[93m]>[e[m]
fi

下面是存储在/~/bash.bashrc中的示例文件/数据,上述代码将其用于测试目的:

if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
PS1='${debian_chroot:+($debian_chroot)}u@h:w$ '
fi

上面的代码包含很多注释。 以下是相同的代码,但注释最少。

#!/bin/bash
#This is the line I want to insert, but sed inteprets it.  
custom_prompt="  PS1='${debian_chroot:+($debian_chroot)}[e[36;40m]u[e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]\$[e[m][e[93m]>[e[m]'"
# delimited version of the prompt that should be acceptable to sed, but isn't.
sed_custom_prompt="  PS1=' ${debian_chroot:+($debian_chroot)}\[\e[36;40m\]\u\[\e[m\]\[\e[93m\]@\[\e[m\]\[\e[36m\]\h\[\e[m\]: \[\e[92m\]\w\[\e[m\] \[\e[92m\]\\$\[\e[m\]$'"
#This is the sed statement that:
#  -finds "PS1="
#  -adds a prefix "#" to comment out the existing line
#  -adds a suffix that begins with a line feed to insert the new line.
sed  -i 's/^*PS1=.*/#&n'"$sed_custom_prompt"'/' ~/bash.bashrc

问题

所以问题和问题是:我该如何解决这个问题?
我开始认为sed不是这项工作的正确工具。 也许我需要切换到perl。

**解决方案** 下面的@kamel cuk 提供了解决此问题的关键。 我手动添加到 $custom_prompt 变量的分隔符是错误的。 Kamal 提供了一个正确分隔变量的 sed 语句。 以下语句生成正确的结果:

sed_custom_prompt=$(<<<"$custom_prompt" sed 's/\/\\/g')
sed  -i 's/^*PS1=.*/#&n'"$sed_custom_prompt"'/' ~/bash.bashrc

这可能对你有用(GNU sed & Bash(:

a='this is variable'
cat <<EOF | sed '/5/!b;s//#&/;r /dev/stdin' <(seq 10)
this is the first added line
this line contains the variable $a => $a <=
this line contains a backslash \ and a dollar $
this is the last line
EOF

如果您不需要任何外壳解释,请使用:

cat <<EOF | sed '/5/!b;s//#&/;r /dev/stdin' <(seq 10)
this is the first added line
this line contains the variable $a => $a <=
this line contains a backslash  and a dollar $
this is the last line
EOF

注:注:EOF之前的.

因此,以下工作:

cat <<'EOF' |
if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
PS1='${debian_chroot:+($debian_chroot)}u@h:w$ '
fi
EOF
sed 's/([[:space:]]+)PS1=.*/1#&n1PS1='''[e[36;40m][e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]$[e[m][e[93m]>[e[m]'''/'

并将输出:

if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
#   PS1='${debian_chroot:+($debian_chroot)}u@h:w$ '
PS1='[e[36;40m][e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]$[e[m][e[93m]>[e[m]'
fi

笔记:

  • 我还匹配了PS1=前面的空格,看起来您希望输出是预期的。
  • 你必须逃避单个刻度。
  • seds/PRE/RE/命令中的表达式RE换行符n是 GNU 扩展。
  • 您不必逃脱$(s命令的右侧既不)也不+。你必须逃离本身。所以你可以这样做:

custom_prompt="  PS1='${debian_chroot:+($debian_chroot)}[e[36;40m]u[e[m][e[93m]@[e[m][e[36m]h[e[m]: [e[92m]w[e[m] [e[92m]\$[e[m][e[93m]>[e[m]'"
# replace each  for double \
sed_custom_prompt=$(<<<"$custom_prompt" sed 's/\/\\/g')
sed 's/([[:space:]]+)PS1=.*/1#&n1'"$sed_custom_prompt"'/'

脚本中存在编码错误:以sed_custom_prompt=开头的行缺少右引号:只需在行尾添加'"并查看是否将正确的输出添加到 ~/bash.bashrc 文件中。

最新更新