2012-11-18 25 views
28

Ho una variabile $data e variabili $file in uno script bash:confrontare il contenuto di due variabili in bash

data=$(echo "$(printf '%s\n' "${array[@]/%/$'\n\n'}")") 
file=$(<scriptfile_results) 

Queste variabili conterrà testo. Come confrontare questi due? Una possibilità è quella di utilizzare diff (1) programma di utilità come questo:

diff -u <(echo "$data") <(echo "$file") 

È questo un modo corretto ed elegante per confrontare il contenuto di due variabili? Inoltre, come viene chiamata la tecnica <()? Mi pare di capire, per ogni <() viene creato un file temporaneo (named pipe) ..

risposta

57

Sì, diff <(echo "$foo") <(echo "$bar") va bene.

Effettuando una ricerca del bash manpage per i personaggi <(, si può trovare che questo è chiamato “sostituzione di processo.”

Non è necessario preoccuparsi della efficienza di creare un file temporaneo, in quanto il file temporaneo è davvero solo una pipe, non un file su disco. Prova questo:

$ echo <(echo foo) 
/dev/fd/63 

Questo dimostra che il file temporaneo è in realtà solo il tubo “descrittore di file 63.” Anche se appare sul /dev filesystem virtuale, il disco non viene mai toccato.

L'effettivo problema di efficienza di cui dovresti preoccuparti qui è la parte "processo" di "sostituzione del processo". Bash forks un altro processo per eseguire lo echo foo. Su alcune piattaforme, come Cygwin, questo può essere molto lento se eseguito frequentemente. Tuttavia, sulla maggior parte delle piattaforme moderne, l'uso di fork è piuttosto veloce. Ho solo provato a fare 1000 sostituzioni di processo in una sola volta eseguendo lo script:

echo <(echo foo) <(echo foo) ... 997 repetitions ... <(echo foo) 

Ci sono voluti 0.225s sul mio vecchio computer portatile Mac, e 2,3 secondi in una macchina virtuale Ubuntu in esecuzione sullo stesso computer portatile. Dividendo per le 1000 invocazioni, questo mostra che le sostituzioni di processo impiegano meno di 3 millisecondi - qualcosa di completamente sminuito dal runtime di diff, e probabilmente non c'è nulla di cui preoccuparsi!

+1

grazie per aver spiegato questo! Sulla mia Xeon [email protected] 'volta per i in {0..1000}; do echo <(echo foo); fatto 'ha preso 0,264 s. – Martin

+2

Si noti che anche "echo foo> foo; gatto foo; rm foo' è anche improbabile che tocchi il disco.Se il file temporaneo viene rimosso prima che il file vfs venga scaricato nella partizione fisica, nulla va mai sul piatto. –

5
test "$data" = "$file" && echo the variables are the same 

Se desiderate essere prolisso, si può anche fare:

if test "$data" = "$file"; then 
    : variables are the same 
else 
    : variables are different 
fi 
+0

esiste un modo per utilizzare effettivamente 'diff' su 2 variabili anziché su 2 file senza scriverli in file temporanei? Mi sono già chiesto questo prima. (quindi puoi vedere cosa c'è di diverso tra loro) –

+0

@ sampson-chen, per quanto ne so, non c'è. Tuttavia, sarebbe bello se qualche esperto programmatore bash lo confermasse. – Martin

1

Questo funziona meglio per me:

var1="cat dog mule pig" 
var2="cat dog ant" 

diff <(echo "$var1") <(echo "$var2") 

Per prima cosa ho impostato var1 e var2. Quindi differisco con gli elementi <() per dire che l'input è una variabile.

2
~ cat test.sh 

#!/usr/bin/env bash 

array1=(cat dog mule pig) 
array2=(cat dog ant) 

diff -ia --suppress-common-lines <(printf "%s\n" "${array1[@]}") <(printf "%s\n" "${array2[@]}") 
+3

Spiega un po 'il tuo codice –

+0

puoi operare con risultato, creare variabili e così via. la mia versione stampa una differenza, per esempio. provalo non danneggerà – deadElk