问题 可以输入if语句吗?


我有一个脚本,如果它运行,每次输出大约10行。这些行的内容各不相同。

我真的希望能够 grep 在输出中,根据输出做不同的事情。

在伪这是我想做的

cat /etc/password | \\
if [ grep "root" $STDOUT ]; then
   echo "root is found"

elif [ grep "nobody" $STDOUT ]; then
   echo "nobody is found"

fi

我用过这里 cat /etc/password 作为一个例子,但它应该用我上面提到的脚本替换。

问题是,我如何获得输出 cat /etc/password 在里面 if/elif 条件?


9850
2018-02-24 10:23


起源

也许awk或perl更适合你的任务.. - bew
不要用 cat 如果意图不显示或连接。在这里你可以在grep命令行中给出文件,因为它被接受,否则你可以只重定向文件(<)。 - Benoit
之后你不需要继续行 |, && 和 || - glenn jackman


答案:


正如@Benoit建议的那样,只需使用 grep 直。

正如@larsmans所说,你可以通过将文件读入变量一次来避免双重读取文件。

鉴于可用性 bash 我这样做:

password=$(< /etc/passwd)

if grep -q root <<< "$password" ; then
    echo root found
elif grep -q nobody <<< "$password" ; then
    echo nobody found
fi

一次读取文件,一次或两次调用 grep,没有推出其他流程或子壳。


6
2018-02-24 11:44



很有趣的解决方案你为什么这么做 IFS= 在第一行? - Sandra Schlichting
在bash中,你可以说 password=$(< /etc/passwd) - glenn jackman
一个好点glenn,我忘记了这一点。 - Sorpigal
@SandraSchlichting:习惯,主要是。这是我在使用时反思性地做的事情 read 并且不希望输入被分割,尽管这里不需要。 - Sorpigal
如果你只是在寻找静态字符串,你可以使用 case 代替 grep  - 根本没有外部流程! - tripleee


你这样做:

if grep -q "root" /etc/passwd ; then
   ...
fi

哪个会起作用 ... 命令如果grep退出代码为0。

记得那个 \[ 是一个外部命令,可能位于 /usr/bin/[ (通常这是一个很难的链接 test 当被调用为 [ 它需要匹配 ] 论据)。另见 陷阱 这里的页面,其中许多交易都与该命令有关。


3
2018-02-24 10:26



+1,但您可能想要添加 -q 至 grep 抑制输出。 - Sorpigal


我建议使用awk:

cat /etc/passwd | awk '/root/{ do something }/nobody/{ do something else }'

您可以使用如下表达式在bash中实现相同的目的:

cat /etc/passwd |
while read; do
  if echo "$REPLY" | fgrep root; then
    something
  fi
  if echo "$REPLY" | fgrep nobody; then
    something_else
  fi
done

但是纯粹的bash解决方案对大型输入的效率较低,因为它运行的是单独的实例 grep 每一行。


3
2018-02-24 11:38



不要用 cat 那样,你可以通过 passwd 直接到 awk, while等等.. - Sorpigal
没错,但这种方式通常更具可读性,因为数据源位于前面,而解析几十行的性能确实不是问题。在这种规模上,这只是个人偏好的问题,而不是投票的理由。 - Michał Kosmulski


使用子shell可以使用if语句,但是当你运行两个时,该解决方案将会中断 grep 管道上的命令,第一个将耗尽它。

您的案例中最好的解决方案可能是阅读 /etc/passwd 变成一个变量,然后 grep 它:

passwd=$(cat /etc/passwd)
if (echo $passwd | grep -q root); then
     echo "root found"
fi
if (echo $passwd | grep -q nobody); then
     echo "nobody found"
fi

2
2018-02-24 10:30



说的更便宜 IFS= read -r -d '' password</etc/passwd 将文件内容读入变量。 - Sorpigal
好的,但我不知道如何保证-1。 - Fred Foo
它没有。我不知道是谁做到了这一点,但我在愤怒中反对投票。 - Sorpigal
感谢那 :) - Fred Foo


只需使用&&:

grep -q root /etc/password && echo "root is found"

grep -q nobody /etc/password && echo "nobody is found"

1
2017-11-06 15:27





在一般情况下,您可以使用临时文件。

t=$(mktemp -t passwd.XXXXXXXX)
trap 'rm $t' 0
trap 'exit 127' 1 2 3 5 15
cat >$t
for u in root nobody; do
  fgrep $u $t
done

traps是之后删除临时文件。

除此之外,你 能够 管道到 if,但第一个 grep在条件内部已经消耗了所有标准输入。它在这样的情况下更有用:

if $option_count ; then
    wc -l
else
    tac
fi <file

0
2018-02-24 15:35





以下怎么样:

#!/bin/bash

if [ -z $1 ]; then
   echo Usage: $0 [UID to search for]
   exit 1;
fi

SEARCHID="$1"

function notFound() {
    echo NOT FOUND 
}

function found() {
    echo Found it
}

function main() {

    grep -i $SEARCHID /etc/passwd
    # Move $? to a variable 
    SEARCHRESULT=$?

    if [ "$SEARCHRESULT" != "0" ]; then
       notFound;
    else
       found;
    fi
}

# call main function
main

0
2017-09-15 14:34