我有一个~/.zshrc
包含以下几行的文件
...
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
##export PATH="/usr/local/opt/[email protected]/bin:$PATH"
##export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
export PATH="/usr/local/opt/[email protected]/bin:$PATH"
export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
...
我正在准备一个小的 bash 脚本,它接受 PHP 版本(第一个参数)和操作(第二个参数)。例如虚拟命令可能如下所示:
mycommand 7.4 comment
这只会注释掉文件中的以下几行:
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
如果你跑
mycommand 7.1 uncomment
将仅更新以下行:
export PATH="/usr/local/opt/[email protected]/bin:$PATH"
export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
所以我的问题是如何使用sed
.sh 脚本中的命令或任何其他命令来解析文件。
我的 bash 脚本如下所示(不起作用)
# File mycommand.sh
# ...
if [[ ! -z "$1" && ! -z "$2" && "$2" = "comment" ]]; then
# remove multi # comments if there's any
sed -i '' 's/#*export PATH="\/usr\/local\/opt\/php@$1/export PATH="\/usr\/local\/opt\/php@$1/g'
# Finally add a single # comment
sed -i '' 's/*export PATH="\/usr\/local\/opt\/php@$1/#export PATH="\/usr\/local\/opt\/php@$1/g'
fi
if [[ ! -z "$1" && ! -z "$2" && "$2" = "uncomment" ]]; then
# remove one or more # comments
sed -i '' 's/#*export PATH="\/usr\/local\/opt\/php@$1/export PATH="\/usr\/local\/opt\/php@$1/g'
fi
答案1
这将稳健、高效且可移植地工作:
#!/usr/bin/env bash
infile=~/.zshrc
tmp=$(mktemp) || exit 1
awk -v ver="$1" -v cmd="$2" '
index($0,"php@"ver"/") {
if ( cmd == "comment" ) { sub(/^#*/,"#") }
else if ( cmd == "uncomment" ) { sub(/^#+/,"") }
else { printf "bad cmd: %s\n", cmd | "cat>&2" }
}
{ print }
' "$infile" > "$tmp" && mv "$tmp" "$infile"
如果需要,请更改"php@"ver"/"
为"export PATH=\"/usr/local/opt/php@"ver"/"
以避免与真实输入中存在但未在示例中显示的其他行发生错误匹配。
如果您有 GNU awk,您可以使用它-i inplace
而不是手动创建 tmp 文件。
答案2
您使用的脚本应更改如下:
if [[ ! -z "$1" && ! -z "$2" && "$2" = "comment" ]]; then
# remove multi # comments if there's any
sed -i "s/#*export PATH=\"\/usr\/local\/opt\/php@$1/export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
# Finally add a single # comment
sed -i "s/export PATH=\"\/usr\/local\/opt\/php@$1/#export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
fi
if [[ ! -z "$1" && ! -z "$2" && "$2" = "uncomment" ]]; then
# remove one or more # comments
sed -i "s/#*export PATH=\"\/usr\/local\/opt\/php@$1/export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
fi
问题是: