我正在尝试编写一个脚本来替换该行:
[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
与该行:
# [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
这将添加新行:
[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \D{%T} \W]\\$ "
到/etc/bashrc
文件。基本上,我希望脚本注释旧设置并在提示中的用户名旁边添加时间戳(新设置)。我尝试像这样做第一部分:
pattern=' [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "'
sudo sed 's/${pattern}/#${pattern}/' < /etc/bashrc
但它不起作用,我认为这是因为字符串中的特殊字符。但我不确定需要转义哪些字符。最后一部分应该是这样的:
sed -i ' [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \D{%T} \W]\\$ "' /etc/bashrc
会给予一些指导。
谢谢
答案1
- 脚本中的单引号
sed
会阻止${pattern}
展开。您必须使用双引号(但这会导致提到的特殊字符问题) - 使用
sed
足够的给定行的寻址来识别它,然后插入注释,如下所示:/^ *\[ *"$PS1 =/s/^/#/
- 使用
a
命令sed
追加给定行
在你的情况下,你只想在行中添加一些东西,所以
sed 's/\( *\[ "$PS1" = "..s-..v...$ " \] && PS1="\[[email protected] \)\(.W]..$ "\)/#\1\2\
\1\\D{%T} \2/' /etc/bashrc
答案2
要使用 sed 进行这种复杂模式的替换:
sed 's/${pattern}/#${pattern}/'
你必须以pattern
这种方式强制评估:
sed 's/'${pattern}'/#'${pattern}'/'
在尝试触摸/etc/bashrc
和使用之前,请检查该临时文件是否完全达到您想要的效果sudo
(此外,在使用之前,sudo
您应该检查您是否确实使用了正确的文件,以避免使用假文件)。
答案3
如果您想在没有正则表达式的情况下替换整行,您也可以先获取行号:
LNO=$(grep -FN "$pattern" </etc/bashrc | cut -d':' -f1)
并将该行替换为注释模式和新行:
[ "$LNO" ] \
&& sed -i "${LNO}s/.*/#$pattern\n$newline/" /etc/bashrc
几个月后读起来也会更清楚。
出于测试目的,我总是喜欢先将 sed 写入临时文件(不带 -i 选项),然后重命名它,这样我就不会损害我的配置。
但我还发现此方法不适用于包含 的模式[,],$ and &
,这些模式还需要按以下顺序进行一些屏蔽:
pattern=${pattern//\[/\\\[}
pattern=${pattern//\]/\\]}
pattern=${pattern//\$/\\$}
pattern=${pattern//\&/\\&}
pattern=${pattern//\\/\\\\}
这导致以下功能:
#!/bin/bash
declare -a commentAndReplaceMask=('[' ']' '$' '&')
function commentAndReplace () {
local p="$1" # pattern
local s="$p" # sed pattern
local r="$2" # replacement
local f="$3" # file
echo args:
echo p: $p
echo r: $r
echo s: $s
s=${s//\\/\\\\}
r=${r//\\/\\\\}
for m in ${commentAndReplaceMask[@]}; do
s=${s//$m/\\$m}
r=${r//$m/\\$m}
done
echo prepared for sed:
echo p: $p
echo r: $r
echo s: $s
LNO=$(grep -Fn "$p" <$f | cut -d':' -f1)
[ "$LNO" ] \
&& sed "${LNO}s/.*/# $s\n$r/" <$f >${f}.tmp
# mv "${f}.tmp" "$f"
}
commentAndReplace "$@"