Как сохранить вывод команды (например, diff) в переменную

21

Я хочу проверить, есть ли какие-либо выходные данные diff(проверить, если файлы одинаковы), если нет echo "Passed $x" else echo "Failed $x". Я придумал какой-то промежуточный шаг (сохранить вывод из diff в файл, а затем прочитать из файла)

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;

Я уверен, что код можно улучшить? Главный вопрос: возможно ли сохранить результат diffнепосредственно в переменной?

Jiew Meng
источник

Ответы:

18

Это работает:

if diff "./helloworld$x.out" "./output/helloworld$x.out"> / dev / null; тогда
    echo "Пройдено $ x";
еще
    echo "Failed $ x";
фи

Если вы используете переменную вместо echoвас, вы можете отбросить elseветку: установите переменную в false перед ifи сохраните 2 строки кода.

Если вы хотите поместить результат в переменную, используйте:

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

Включая мой тест, чтобы увидеть, действительно ли он работает:

rinzwind @ discworld: ~ $ touch 1
rinzwind @ discworld: ~ $ touch 2
rinzwind @ discworld: еще $ тест
если diff 1 2> / dev / null; тогда
    echo "Пройдено $ x";
еще
    echo "Failed $ x";
фи
rinzwind @ discworld: ~ $ ./test
Прошло 

rinzwind @ discworld: ~ $ vi 2
rinzwind @ discworld: ~ $ больше 2
2
rinzwind @ discworld: ~ $ ./test
Не удалось 

Со >/dev/nullстороны: >/dev/null 2>&1отправит выходные данные >/dev/nullи 2>&1 отправит стандартные ошибки в тот же файл ( &1означает «использовать первый параметр») перед этой командой (поэтому она также использует /dev/null).

sidenote: sdiffпокажет параллельные diffсписки:

SDIF 1 2 
1 1
2 2
3 3
4 4
5 5
7 7
                                  > 8
9 9
10 10
Rinzwind
источник
Спасибо, это работает, но я не понимаю, что ... > /dev/nullделает в этом контексте. Вывод diff будет идти в / dev / null, но разве это ничего?
Jiew Meng
1
Разница выведет все различия между файлами на вашем экране, и> / dev / null убедится, что вывод команды перенаправлен в забвение. If все еще выполняется на основе вывода.
Rinzwind
1
Оператор if проверяет код завершения команды diff. 0 означает, что различий не обнаружено, а 1 означает, что было одно или несколько различий.
Кнут Элдхусет
17

diff может даже полностью подавить вывод, за исключением сообщений «Files / bin / bash и / bin / sh другому», используя код ниже.

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

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

Если вы даже хотите скрыть это сообщение, вам нужно добавить > /dev/nullпосле команды diff, чтобы скрыть вывод diff:

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

/dev/null это специальный файл, который действует как черная дыра, если вы напишите в него, он исчезнет, ​​если вы читаете из него, вы ничего не получите обратно.

Обратите внимание, что bash не нужно ;заканчивать строки.

Что касается исходного вопроса, чтобы сохранить вывод программы в переменной:

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

Альтернативные способы проверить, является ли переменная пустой:

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

Если вы используете Bash, последние две команды рекомендуются для сравнения строк. В противном случае первое и [ -n "$output" ]рекомендуется.

Lekensteyn
источник
6

а) Вывод команды 1 может быть пойман с

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

или с обратными галочками, но это не рекомендуется, потому что вы не можете их вкладывать, и их может быть трудно отличить от апострофа, в зависимости от шрифта:

 output=`cmd1`

б) Вместо того, чтобы записывать в файл, а затем читать этот файл (или захватывать вывод, а затем повторять его), вы бы напрямую использовали канал:

 cmd1 > file
 cat file | cmd2 

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

=>

 cmd1 | cmd2 

но в вашем примере вас интересует не результат, а результат программы - сработало ли это?

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

Прочитать об использовании && и || поиск "ярлык И и ярлык ИЛИ".

Чтобы сохранить вывод в чистоте, вы можете перенаправить вывод 'diff' в никуда:

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

Чтобы получить успех и оценить его позже, вы сохраните результат последней команды в переменной с $ ?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
неизвестный пользователь
источник
3

Если вы хотите знать, являются ли два файла одинаковыми или различаются (но не волнует, в чем на самом деле разница), то вам cmpбольше подойдет.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
geirha
источник