Jak zapisać dane wyjściowe z polecenia (np. Diff) w zmiennej

21

Chcę przetestować, czy jest jakieś wyjście z diff(sprawdź, czy pliki są takie same), jeśli nie ma echo "Passed $x" else echo "Failed $x". Wpadłem na jakiś krok pośredni (zapisz dane wyjściowe z pliku diff do pliku, a następnie przeczytaj plik)

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;

Jestem pewien, że kod można poprawić? Główne pytanie brzmi: czy można zapisać dane wyjściowe diffbezpośrednio w zmiennej?

Jiew Meng
źródło

Odpowiedzi:

18

To działa:

if diff "./helloworld$x.out" "./output/helloworld$x.out"> / dev / null; następnie
    echo „Przeszedł $ x”;
jeszcze
    echo „Failed $ x”;
fi

Jeśli użyjesz zmiennej zamiast echo możesz upuścić elserozgałęzienie: ustaw zmienną na false przed ifi zapisz 2 linie kodu.

Jeśli chcesz umieścić wynik w zmiennej, użyj:

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

Łącznie z moim testem, aby sprawdzić, czy to naprawdę działa:

rinzwind @ discworld: ~ $ touch 1
rinzwind @ discworld: ~ $ touch 2
rinzwind @ discworld: ~ $ więcej testów
jeśli diff 1 2> / dev / null; następnie
    echo „Przeszedł $ x”;
jeszcze
    echo „Failed $ x”;
fi
rinzwind @ discworld: ~ $ ./test
Przeszedł 

rinzwind @ discworld: ~ $ vi 2
rinzwind @ discworld: ~ $ więcej 2
2)
rinzwind @ discworld: ~ $ ./test
Nie powiodło się 

Po >/dev/nullczęści: >/dev/null 2>&1wyśle ​​dane wyjściowe >/dev/nulli 2>&1 wyśle ​​standardowe błędy do tego samego pliku ( &1oznacza „użyj pierwszego parametru”) przed tym poleceniem (więc również używa /dev/null).

sidenote: sdiffpokaże listę obok siebie diff:

sdiff 1 2 
1 1
2 2
3 3
4 4
5 5
7 7
                                  > 8
9 9
10 10
Rinzwind
źródło
Dzięki, działa, ale nie rozumiem, co ... > /dev/nullrobi w tym kontekście. Wyjście diff będzie goto / dev / null, ale czy to nic?
Jiew Meng,
1
Różnica wyświetli wszystkie różnice między plikami na ekranie, a> / dev / null upewni się, że wyjście polecenia zostanie przekierowane do zapomnienia. If jest nadal wykonywane na podstawie danych wyjściowych.
Rinzwind,
1
Instrukcja if sprawdza kod wyjścia polecenia diff. 0 oznacza, że ​​nie znaleziono różnic, a 1 oznacza, że ​​istniała jedna lub więcej różnic.
Knut Eldhuset
17

diff może nawet całkowicie wyłączyć dane wyjściowe, z wyjątkiem komunikatu „Pliki / bin / bash i / bin / sh różnią się” za pomocą poniższego kodu.

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

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

Jeśli nawet chcesz ukryć tę wiadomość, musisz dołączyć > /dev/nullpo poleceniu diff, aby ukryć wynik diff:

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

/dev/null to specjalny plik, który działa jak blackhole, jeśli do niego napiszesz, zniknie, jeśli z niego czytasz, nic nie odzyskasz.

Zauważ, że bash nie musi ;kończyć linii.

Jeśli chodzi o oryginalne pytanie, aby zapisać dane wyjściowe programu w zmiennej:

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

Alternatywne sposoby sprawdzenia, czy zmienna jest pusta:

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

Jeśli używasz Bash, do porównania ciągów zalecane są dwa ostatnie polecenia. W przeciwnym razie pierwszy i[ -n "$output" ] jest zalecany.

Lekensteyn
źródło
6

a) Dane wyjściowe polecenia 1 można złapać

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

lub z backtickami, ale są one odradzane, ponieważ nie można ich zagnieżdżać i mogą być trudne do odróżnienia od apostrofów, w zależności od czcionki:

 output=`cmd1`

b) Zamiast zapisywać do pliku, a następnie czytać ten plik (lub pobierać dane wyjściowe, a następnie je echo), użyłbyś potoku bezpośrednio:

 cmd1 > file
 cat file | cmd2 

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

=>

 cmd1 | cmd2 

ale w twoim przykładzie nie interesuje Cię wynik, ale wynik programu - czy to zadziałało?

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

Aby przeczytać o użyciu && i || wyszukaj „skrót AND i skrót OR”.

Aby utrzymać wyjście w czystości, możesz przekierować wyjście „diff” do nikąd:

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

Aby złapać sukces i ocenić go później, przechowujesz wynik ostatniego polecenia w zmiennej z $ ?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
nieznany użytkownik
źródło
3

Jeśli chcesz wiedzieć, czy dwa pliki są takie same lub różnią się (ale nie obchodzi, co to właściwie jest różnica), cmpbardziej odpowiednie.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
geirha
źródło