在 Bash 中对文件内容进行复合检查

在 Bash 中对文件内容进行复合检查

我正在尝试使用 Bash 中的 new-test 编写复合 if 语句。我想检查一个文件是否存在,以及另外两个文件是否具有特定内容。当嵌套在测试中时,我的 grep 搜索似乎不太好用。

echo "a" >> file_a
echo "b" >> file_b 
echo "c" >> file_c
if [[ -f file_a && \
  $(grep -q "b" file_b) && \
  $(grep -q "c" file_c) ]]; then
  echo "Got 'em"
fi

答案1

当测试命令的退出状态(例如grep)时,您不需要或不想要[[ ]]$( )或任何这些东西。检查和if之间的任何退出状态,并根据其成功或失败采取适当的分支。ifthen

$( )存在的目的是为了捕获命令的输出(即运行时打印的内容 -grep -q不打印任何内容),并将其用作另一个命令的一部分。这根本不是你想要的。

[[ ]]评估测试表达式(例如,可以测试文件是否存在、两个字符串是否相等等),并将结果转换为退出状态。但由于grep -q它已经产生了退出状态,因此您不需要进行某种测试来将其转换为该形式。

需要[[ ]]检查 file_a 是否存在,但这是它在这里唯一要扮演的角色。并且您需要&&创建一个复合命令,只有当它的所有部分都成功时,该命令才会成功。因此,您需要的是:

...
if [[ -f file_a  ]] && 
  grep -q "b" file_b &&
  grep -q "c" file_c; then
...

答案2

您可以从 grep 中删除-q,并使用该标志测试命令替换内的表达式是否不为空-n

if [[ -f file_a && -n $(grep "b" file_b) && -n $(grep "c" file_c)  ]]; then
  echo "Got 'em"
fi
  • 虽然可以省略,但它会像在测试内部-n有标志一样工作。-n

  • 通常, 如果您只是要使用 grep 测试模式匹配,则不需要if子句和[[或。[

答案3

或者,完全去掉“如果”:

test -f file_a && grep -q "b" file_b && grep -q "c" file_c && echo "Got em"

答案4

grep成功时退出代码为 0,但需要test真值。您必须反转 grep 的退出代码或检查它是否以 0 退出:

if [[ -f file_a && \
      ! $(grep -q "b" file_b) && \
      ! $(grep -q "c" file_c) ]]; then
  echo "Got 'em"
fi

或者

if [[ -f file_a && \
      $(grep -q "b" file_b) -eq 0 && \
      $(grep -q "c" file_c) -eq 0 ]]; then
  echo "Got 'em"
fi

理想情况下,有一种比将其放入子 shell 中更易读的方法$()

相关内容