目标我正在尝试编写一个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=
前面的空格,看起来您希望输出是预期的。 - 你必须逃避单个刻度。
sed
s/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 文件中。