我有一组配置文件,我想注释掉主题中包含该配置行的目录中所有文件中的一些配置。
配置文件如下所示:
...
someconfig = comand()#@#$#$@#
asdbaksdjbkajsbd
asdasdjhavshdjvas
...
所以我决定使用 bash 脚本来做到这一点
#!/bin/bash
filename='myconfigfile.conf'
echo Start ...
while IFS= read -r line; do
if [[ $line =~ ^someconfig.* ]]; then
echo "$line"
sed -i 's/$line/\#\$line/g' $filename
fi
done < $filename
该文件中的首选输出行:
...
#someconfig = comand()#@#$#$@#
# asdbaksdjbkajsbd
# asdasdjhavshdjvas
...
我在 python 中做到了这一点,但我想看看是否可以在 bash 脚本中做到这一点,而不会使它变得太复杂。
我有一个解决方案,通过使用布尔值和迭代遍历所有文件来检测下一行以非空格字符开头来更改所有文件中的这些行,但我不知道如何替换部分,而且我的代码似乎不正在工作。
任何帮助将不胜感激。
答案1
该问题的实施存在问题且效率低下。
您逐行读取文件并sed
从输入行构造命令。如果该行包含任何正则表达式特殊字符(例如.^$[]
等),则此命令可能会出现意外行为。
sed
然后,对于必须更改的每一行,您都需要处理一次整个文件。您可以单独处理每一行,而不是重复处理整个输入文件。
我建议使用awk
处理该文件并使用处理临时输出文件的 shell 脚本包装器。 (awk
不支持就地编辑,如sed
或perl
。)
#!/bin/bash
filename='myconfigfile.conf'
temp=${filename}.temp
awk '/^[^ ]/ { comment=0 } # stop commenting if line starts with non-space.
/^someconfig/ { comment=1 } # start commenting if line starts with "someconfig"
comment {$0 = "#" $0} # prepend "#" to whole line ($0)
{ print }' $filename > $temp && mv -f $temp $filename || rm -f $temp
您可以选择添加规则
/^[ ]*$/ { comment=0 } # stop commenting on empty line or space only
当出现空行或仅包含空格的行时停止注释。
请注意,[^ ]
和[ ]
包含一个空格和一个制表符。
脚本没有探测任何缩进。只要非零,它就会简单地添加"#"
到行中的任何内容(包括缩进)之前。comment
答案2
如果您已经在 shell 中逐行处理文件,为什么还要使用 sed 或 awk?像这样的东西不需要使用一堆其他程序就可以工作。
[[ $line =~ '^[[:space:]]' ]] || indent=0
if [[ $line =~ ^someconfig.* || $indent ]]
then
echo -n "#"
indent=1
fi
echo "$line"
将循环输出发送到临时文件,然后mv
如(也非常好的)awk 答案所示:
done <$file >$file.tmp && mv $file.tmp $file
我通常更喜欢将重命名与 && 链接起来,这样如果命令失败就不会发生这种情况。另外,对于任何拼写错误,我们深表歉意 - 我是在手机上输入的,并且很难在手机键盘上编写代码。 :)