仅当该行还不是文件的一部分时才在文件中插入一行

Dre*_*mor 2 grep scripting bash shell-script

我正在搜索创建一个脚本来自动将一些自定义配置应用于基于文本的配置文件。

在本例中,/etc/sysctl.conf如果这些行尚未在文件中,我正在搜索添加 2 行(以避免在文件中多次出现这些行)。

这是我使用的脚本:

if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
echo vm.vfs_cache_pressure=50 | sudo tee -a /etc/sysctl.conf
fi
if [ `grep vm.vfs_cache_pressure /etc/sysctl.conf` != "vm.vfs_cache_pressure=50" ]; then
echo vm.vfs_cache_pressure=50 | sudo tee -a /etc/sysctl.conf
fi
Run Code Online (Sandbox Code Playgroud)

和我得到的错误:

/home/erwan/Workspace/Install.sh: ligne 19 : [: != : opérateur unaire attendu
/home/erwan/Workspace/Install.sh: ligne 23 : [: != : opérateur unaire attendu
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

gol*_*cks 7

这是个问题:

if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
Run Code Online (Sandbox Code Playgroud)

由于 ifgrep没有找到任何东西,它不会输出任何东西,而且它的左侧将什么都没有,这是一个错误。如果它确实找到了一些东西,这也是一个问题,因为输出可能包含空格(例如,如果vm.swappiness在文件中多次出现)。这需要被引用,否则在展开时它会显示为一系列不同的字符串。

因此,您应该使用,if [ "$(grep ...)" ]以便引用输出。如果没有输出,你有"",这在 bash 测试的任何一侧都很好。

但是,在这种情况下,我建议改用grep的退出状态。来自man grep

退出状态

通常,如果找到选定的行,退出状态为 0,否则为 1。但如果发生错误,退出状态为 2...

这里也有用的是-q开关:

-q, --quiet, --silent

安静的; 不要向标准输出写入任何内容。如果找到任何匹配项,即使检测到错误,也立即以零状态退出。

因此,请记住$?最后完成的前台进程的退出状态:

grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then
Run Code Online (Sandbox Code Playgroud)

如果grep未找到任何内容且未发生错误,则此条件为真。

  • `if` 直接作用于命令,所以你甚至可以把它写成 `if !grep -q not_found /etc/sysctl.conf; 然后...;fi`。 (2认同)