Como salvar a saída do comando (por exemplo, diff) em uma variável

21

Quero testar se há alguma saída do diff(teste se os arquivos forem iguais), se não houver echo "Passed $x" else echo "Failed $x". Eu vim com uma etapa intermediária (salve a saída do diff para um arquivo e depois leia o arquivo)

diff "./helloworld$x.out" "./output/helloworld$x.out" > tmp.txt;
output="`cat tmp.txt`";

if [ "$output" = "" ];
  then
    echo "Passed $x";
  else
    echo "Failed $x";
  fi;

Tenho certeza de que o código pode ser melhorado? A principal questão é: é possível salvar a saída diffdiretamente em uma variável?

Jiew Meng
fonte

Respostas:

18

Isso funciona:

if diff "./helloworld$x.out" "./output/helloworld$x.out"> / dev / null; então
    eco "Passou $ x";
outro
    eco "Falhou $ x";
fi

Se você usar uma variável em vez de echoeliminar a elseramificação: defina a variável como false antes de ife salve 2 linhas de código.

Se você realmente deseja colocar o resultado em um uso variável:

some_var="$(diff "./helloworld$x.out" "./output/helloworld$x.out")"

Incluindo meu teste para ver se ele realmente funciona:

rinzwind @ discworld: ~ $ touch 1
rinzwind @ discworld: ~ $ toque em 2
rinzwind @ discworld: ~ $ mais teste
se diff 1 2> / dev / null; então
    eco "Passou $ x";
outro
    eco "Falhou $ x";
fi
rinzwind @ discworld: ~ $ ./test
Passado 

rinzwind @ discworld: ~ $ vi 2
rinzwind @ discworld: ~ $ mais 2
2
rinzwind @ discworld: ~ $ ./test
Falhou 

Por >/dev/nullparte: >/dev/null 2>&1enviará a saída para >/dev/nulle 2>&1 enviará erros padrão para o mesmo arquivo ( &1significa 'use first parameter') na frente deste comando (que também usa /dev/null).

sidenote: sdiffmostrará uma difflista lado a lado :

sdiff 1 2 
1 1
2 2
3 3
4 4
5 5
7 7
                                  > 8
9 9
10 10
Rinzwind
fonte
Obrigado, funciona, mas eu não entendo o que ... > /dev/nullfaz neste contexto. A saída do diff vai para / dev / null, mas não é nada?
precisa saber é o seguinte
1
O diff exibirá todas as diferenças entre os arquivos na tela e> / dev / null garante que a saída do comando seja redirecionada para o esquecimento. O if ainda é executado com base na saída.
Rinzwind
1
A instrução if verifica o código de saída do comando diff. 0 significa que não foram encontradas diferenças, enquanto 1 significa que houve uma ou mais diferenças.
Knut Eldhuset
17

diff pode até suprimir completamente a saída, exceto a mensagem "Arquivos / bin / bash e / bin / sh differ" usando o código abaixo.

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"

if diff -q "$file1" "$file2"; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Se você quiser ocultar essa mensagem, adicione > /dev/nulldepois do comando diff para ocultar a saída de diff:

if diff -q "$file1" "$file2" >/dev/null; then

/dev/null é um arquivo especial que age como um buraco negro; se você escrever nele, ele desaparecerá; se você estiver lendo, não receberá nada de volta.

Observe que o bash não precisa ;terminar as linhas.

Quanto à pergunta original, para salvar a saída de um programa em uma variável:

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"
output="$(diff -q "$file1" "$file2")"

# the quotes are mandatory, this checks whether $output is empty or not
if [ -n "$output" ]; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Maneiras alternativas de verificar se uma variável está vazia:

[ "$output" = "" ]
[ "$output" == "" ]
[[ "$output" == "" ]]
[[ $output == "" ]]

Se você estiver usando o Bash, os dois últimos comandos serão recomendados para comparação de cadeias. Caso contrário, o primeiro e [ -n "$output" ]é recomendado.

Lekensteyn
fonte
6

a) A saída do comando1 pode ser capturada com

output=$(diff "helloworld$x.out" "output/helloworld$x.out") 

ou com backticks, mas esses são desencorajados, porque você não pode aninhar neles, e pode ser difícil distinguir dos apóstrofos, dependendo da fonte:

 output=`cmd1`

b) Em vez de gravar em um arquivo e, em seguida, ler esse arquivo (ou pegar a saída e repeti-la), você usaria um canal diretamente:

 cmd1 > file
 cat file | cmd2 

 output=$(cmd1)
 echo "${output}" | cmd2 

=>

 cmd1 | cmd2 

mas no seu exemplo, você não está interessado no resultado, mas no resultado do programa - funcionou?

 diff "helloworld$x.out" "output/helloworld$x.out" && echo "success" || echo "failure" 

Para ler sobre o uso de && e || procure por "atalho AND e atalho OR".

Para manter a saída limpa, você pode redirecionar a saída de 'diff' para lugar nenhum:

 diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null && echo "success" || echo "failure" 

Para obter sucesso e avaliá-lo mais tarde, você armazena o resultado do último comando em uma variável com $ ?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
Usuário desconhecido
fonte
3

Se você quiser saber se dois arquivos são iguais ou diferentes (mas não se importa com a diferença), cmpé mais adequado.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
Geirha
fonte