web-dev-qa-db-fra.com

obtenir la sortie et la valeur de retour de grep en une seule opération dans bash

J'écris un script bash; J'exécute une certaine commande et grep.

pfiles $1 2> /dev/null | grep name # $1 Process Id

La réponse sera quelque chose comme:

sockname: AF_INET6 ::ffff:10.10.50.28  port: 22
peername: AF_INET6 ::ffff:10.16.6.150  port: 12295

La réponse peut être sans ligne, 1 ligne ou 2 lignes.
Dans le cas où grep ne renvoie aucune ligne (code de retour grep 1), j'interromps le script; si j'obtiens 1 ligne j'invoque A() ou B() si plus de 1 ligne. Le code retour de grep est 0 lorsque la sortie est 1-2 lignes.

grep a une valeur de retour (0 ou 1) et une sortie.
Comment puis-je les attraper tous les deux? Si je fais quelque chose comme:

OUTPUT=$(pfiles $1 2> /dev/null | grep peername)

La variable OUTPUT aura alors la sortie (chaîne); Je veux également la valeur booléenne de l'exécution de grep.

7
ilansch

Vous pouvez utiliser

output=$(grep -c 'name' inputfile)

La variable output contiendra alors le nombre 0, 1, ou 2. Ensuite, vous pouvez utiliser une instruction if pour exécuter différentes choses.

11
pfnuesel

C'est assez simple:

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
grep_return_code=$?

Si une substitution de commande $(…) est affectée à une variable, $? Obtiendra le code retour de la dernière commande dans $(…). Et, bien sûr, vous n'avez pas besoin de vous référer explicitement à $?; vous pouvez faire des choses comme

si OUTPUT = $ (pfiles "$ 1" 2>/dev/null | grep peername) 
 alors 
 # le reste du script
                ︙
Fi

ou

si ! OUTPUT = $ (pfiles "$ 1" 2>/dev/null | grep peername) 
 Puis 
 Quitter 
 Fi 
 # le reste du script

Cette approche est utile dans les situations où sortie de la commande et son code retour (a.k.a. exit status) ne sont pas corrélés. Mais, pour grep, ils sont fortement corrélés: s'il a produit une sortie, il a réussi. S'il n'a pas produit de sortie, il a échoué. Alors pourquoi ne pas simplement tester le sortie?

OUTPUT = $ (pfiles "$ 1" 2>/dev/null | grep peername) 
 Si ["$ OUTPUT"] 
 Alors 
 # le reste du script
                ︙
Fi

ou

OUTPUT = $ (pfiles "$ 1" 2>/dev/null | grep peername) 
 Si [-z "$ OUTPUT"] 
 Puis 
 Sortir 
 Fi 
 # le reste du script

P.S. Vous devez toujours citer vos références de variables Shell (par exemple, "$1") Sauf si vous avez une bonne raison de ne pas le faire et que vous êtes sûr de savoir ce que vous faites.

1
Scott

Si vous avez besoin du résultat de grep, vous ne pouvez pas utiliser le -c drapeau comme indiqué dans l'autre réponse. Ce que vous pouvez faire, cependant, est exécuté deux fois, une fois avec -c flag pour obtenir le nombre de correspondances et une sans -c flag, pour voir les correspondances. Cependant, cela peut être très inefficace, selon la taille de votre fichier d'entrée.

Vous pouvez faire quelque chose comme ça:

Contenu de entrée:

The first line is foo
I have a drink at the bar
The third line is foo again

Contenu de script:

#!/usr/bin/env bash

countMatches(){
    echo Searching for "${1}"
    result=$(grep "${1}" input)
    if [ $? -eq 1 ]; then
        echo No match found
        echo
        exit 1
    fi

    if [ $(echo "${result}" | wc -l) -eq 1 ]; then
        echo 1 match found:
        echo "${result}"
        echo
    else
        echo 2 matches found:
        echo "${result}"
        echo
    fi
}

countMatches foo
countMatches bar
countMatches baz

Et voici la sortie lorsque vous invoquez le script:

Searching for foo
2 matches found:
The first line is foo
The third line is foo again

Searching for bar
1 match found:
I have a drink at the bar

Searching for baz
No match found
1
pfnuesel

Essayez ce code, je pense, il fait ce que vous voulez.

  1. Je mets la sortie grep dans la variable OUTPUT
  2. Je pense que vous n'avez pas besoin du statut de sortie grep comme valeur booléenne. C'est 0 ou 1, et cela ne convient pas à votre tâche. Vous avez besoin d'un nombre de lignes - 0, 1, 2, etc. Par conséquent, comptez les lignes dans la variable OUTPUT et mettez ce nombre dans la deuxième variable - line_count. Nous aurons deux variables dans le résultat. D'abord avec la sortie grep, ensuite avec la quantité de lignes.
  3. Puis vérifier line_count dans l'instruction case et effectuez l'action requise.

tilisation:./switching_by_grep_result.sh your_file.txt

#!/bin/bash

# your code
OUTPUT=$(pfiles $1 2> /dev/null | grep name) # $1 Process Id

# count lines in the OUTPUT variable by using 'grep -c'
line_count=$(echo -n "$OUTPUT" | grep -c '^')

# checks lines count in here and invokes needed script or exit.
# if 0 lines - exit
# if 1 lines - invoke A
# if any other number of lines - invoke B
case $line_count in  
    0) echo 'exit'
    ;;  
    1) echo 'A() script invoking here'
    ;;  
    *) echo 'B() script invoking here'
    ;;  
esac
0
MiniMax