obtém a saída e o valor de retorno do grep em uma única operação no bash

4

Eu estou escrevendo um script bash; Eu executo um certo comando e grep.

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

A resposta será algo como:

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

A resposta pode ser sem linhas, 1 linha ou 2 linhas.
No caso de o grep não retornar linhas (grep return code 1), eu aborto o script; se eu obtiver 1 linha, invoco A () ou B () se houver mais de uma linha. O código de retorno do grep é 0 quando a saída é de 1-2 linhas.

grep tem valor de retorno (0 ou 1) e saída.
Como posso pegar os dois? Se eu fizer algo como:

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

Então a variável OUTPUT terá a saída (string); Eu também quero o valor booleano da execução do grep.

    
por ilansch 22.06.2017 / 17:10

4 respostas

3

Você pode usar

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

A variável output conterá então o número 0 , 1 ou 2 . Então você pode usar uma declaração if para executar coisas diferentes.

    
por 22.06.2017 / 17:19
1

Se você precisar do resultado de grep , não poderá usar a -c sinalizada na outra resposta. O que você pode fazer, no entanto, é executar duas vezes, uma vez com -c flag para obter o número de correspondências e uma sem -c flag, para ver as correspondências. No entanto, isso pode ser muito ineficiente, dependendo do tamanho do arquivo de entrada.

Você pode fazer algo assim:

Conteúdo da entrada :

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

Conteúdo do 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

E aqui está a saída quando você invoca o 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
    
por 22.06.2017 / 23:20
1

Isso é bem simples:

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

Se uma substituição de comando $(…) for atribuída a uma variável, $? obterá o código de retorno do último comando no $(…) . E, claro, você não precisa se referir a $? explicitamente; você pode fazer coisas como

if OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
then
    # the rest of the script
                ︙
fi

ou

if ! OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
then
    exit
fi
# the rest of the script

Essa abordagem é útil em situações em que a saída do comando e seu código de retorno (a.k.a. status de saída) não está correlacionado. Mas, para grep , eles são altamente correlacionados: Se produziu saída, conseguiu. Se não produziu a saída, falhou. Então, por que não apenas testar a saída ?

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
if [ "$OUTPUT" ]
then
    # the rest of the script
                ︙
fi

ou

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
if [-z "$OUTPUT" ]
then
    exit
fi
# the rest of the script

P.S. Você deve sempre citar suas referências de variáveis de shell (por exemplo, "$1" ) a menos que você tenha uma boa razão para não e você tem certeza de que sabe o que está fazendo.

    
por 26.06.2017 / 00:28
0

Tente esse código, sinto, fazendo o que você quer.

  1. eu coloquei grep output na variável OUTPUT
  2. Eu acho que você não precisa do grep exit status como valor booleano. É 0 ou 1 e não corresponde à sua tarefa. Você precisa de quantidade de linhas - 0, 1, 2, etc. Portanto, conte as linhas na variável OUTPUT e coloque esse número na segunda variável - line_count . Nós teremos duas variáveis no resultado. Primeiro com saída grep, segundo com quantidade de linhas.
  3. Em seguida, verifique line_count na instrução case e execute a ação necessária.

Uso: ./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
    
por 25.06.2017 / 21:36