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

21

Eu quero testar se há alguma saída do diff (teste se os arquivos são iguais), se nenhum echo "Passed $x" else echo "Failed $x" . Eu criei um passo intermediário (salve a saída do diff em um arquivo e depois leia do 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 questão principal é: é possível salvar a saída de diff diretamente em uma variável?

    
por Jiew Meng 13.08.2011 / 15:07

4 respostas

18

Isso funciona:

if diff "./helloworld$x.out" "./output/helloworld$x.out" >/dev/null; then
    echo "Passed $x";
else
    echo "Failed $x";
fi

Se você usar uma variável em vez de echo , poderá descartar else branche: defina a variável como false antes de if e salve 2 linhas de código.

Se você quiser realmente colocar o resultado em uma variável use:

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

Incluindo meu teste para ver se realmente funciona:

rinzwind@discworld:~$ touch 1
rinzwind@discworld:~$ touch 2
rinzwind@discworld:~$ more test
if diff 1 2 >/dev/null; then
    echo "Passed $x";
else
    echo "Failed $x";
fi
rinzwind@discworld:~$ ./test
Passed 

rinzwind@discworld:~$ vi 2
rinzwind@discworld:~$ more 2
2
rinzwind@discworld:~$ ./test
Failed 

Na >/dev/null part: >/dev/null 2>&1 enviará a saída para >/dev/null e 2>&1 enviará erros padrão para o mesmo arquivo ( &1 significa 'use primeiro parâmetro') na frente deste comando (assim ele também usa /dev/null ).

sidenote: sdiff mostrará uma listagem diff lado-a-lado:

sdiff 1 2 
1                               1
2                               2
3                               3
4                               4
5                                  5
7                               7
                                  > 8
9                               9
10                              10
    
por Rinzwind 13.08.2011 / 15:15
17

diff pode até suprimir a saída completamente, exceto pela mensagem "Files / 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 mesmo ocultar essa mensagem, você deve anexar > /dev/null após o comando diff para ocultar a saída de diff :

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

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

Observe que o bash não precisa de ; para as linhas finais.

Quanto à pergunta original, salve 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

Formas alternativas para verificar se uma variável está vazia:

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

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

    
por Lekensteyn 13.08.2011 / 15:50
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-los, e eles podem ser difíceis de distinguir de apostrofs, 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, em seguida, ecoar), 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 na saída, mas no resultado do programa - funcionou?

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

Para ler sobre o uso de & amp; & amp; e || pesquise "atalho E 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
    
por user unknown 13.08.2011 / 16:17
3

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

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
    
por geirha 14.08.2011 / 00:13