Bash: проверить взаимное равенство нескольких переменных? - PullRequest
1 голос
/ 11 января 2012

Как правильно проверить, если несколько переменных равны?

if [[ $var1 = $var2 = $var3 ]] # syntax error

Нужно ли писать что-то вроде следующего?

if [[ $var1 = $var2 && $var1 = $var3 && $var2 = $var3 ]] # cumbersome
if [[ $var1 = $var2 && $var2 = $var3 && $var3 = $var4 ]] # somewhat better

К сожалению, превосходное руководство по Advanced Bash Scripting и другие источники в Интернете, которые я мог найти, не дают такого примера.

Моя особая мотивация - проверить, имеют ли несколько каталогов одинаковое количество файлов, используя ls -1 $dir | wc -l для подсчета файлов.

Примечание
"var1" и т. д. являются примерами переменных. Я ищу решение для произвольных имен переменных, а не только с предсказуемым числовым окончанием.

Обновление
Я принял ответ Ричо, так как он самый общий. Тем не менее, я на самом деле использую Кайл, потому что он самый простой, и мои входные данные гарантированно позволят избежать предостережения.

Спасибо за предложения, все.

Ответы [ 5 ]

3 голосов
/ 11 января 2012

, если вы хотите проверить равенство произвольного числа элементов (назовем их $ item1-5, но они могут быть массивом

st=0
for i in $item2 $item3 $item4 $item5; do
    [ "$item1" = "$i" ]
    st=$(( $? + st ))
done

if [ $st -eq 0 ]; then
    echo "They were all the same"
fi
2 голосов
/ 02 декабря 2013

Если это отдельные слова, вы можете обойтись очень дешево.

varUniqCount=`echo "${var1} ${var2} ${var3} ${var4}" | sort -u | wc -l`
if [ ${varUniqCount} -gt 1 ]; then
   echo "Do not match"
fi
1 голос
/ 11 января 2012

Переходный метод обследования.

#!/bin/bash

var1=10
var2=10
var3=10

if [[ ($var1 == $var2) && ($var2 == $var3) ]]; then 
    echo "yay"
else
    echo "nay"
fi

Вывод:

[jaypal:~/Temp] ./s.sh 
yay

Примечание:

Поскольку вы указали в своем вопросе, что ваша цель - проверить несколько каталогов с одинаковым номеромфайлов, я подумал о следующем решении.Я знаю, что это не то, что вы просили, поэтому, пожалуйста, не стесняйтесь игнорировать это.

Шаг 1:

Определение количества файлов в данном каталоге.Эта команда также будет искать внутри подкаталогов, но этим можно управлять, используя опцию -depth из find.

[jaypal:~/Temp] find . -type d -exec sh -c "printf {} && ls -1 {} | wc -l " \;
.       9
./Backup       7
./bash       2
./GTP      22
./GTP/ParserDump      11
./GTP/ParserDump/ParserDump       1
./perl       7
./perl/p1       2
./python       1
./ruby       0
./scripts      22

Step2:

Это можно комбинировать с Step1, так как мы просто перенаправляем содержимое в файл.

[jaypal:~/Temp] find . -type d -exec sh -c "printf {} && ls -1 {} | wc -l " \; > file.temp

Step3:

Используя следующую команду, мы дважды заглянем в файл file.temp, и он выдаст нам список каталогов с одинаковым количеством файлов.

[jaypal:~/Temp] awk 'NR==FNR && a[$2]++ {b[$2];next} ($2 in b)' file.temp file.temp | sort -k2
./GTP/ParserDump/ParserDump       1
./python       1
./bash       2
./perl/p1       2
./Backup       7
./perl       7
./GTP      22
./scripts      22
1 голос
/ 11 января 2012

Для вашего конкретного случая это должно работать:

distinct_values=$(for dir in this_dir that_dir another_dir ; do ls -l "$dir" | wc -l ; done | uniq | wc -l)
if [ $distinct_values -eq 1 ] ; then
    echo All the same
else
    echo Not all the same
fi

Пояснение:

  • ls -l "$dir" перечисляет файлы и подкаталоги в каталоге, по одному на строку (без точечных файлов).
  • Передача вывода через wc -l дает вам количество файлов в каталоге.
  • Выполнение этого последовательно для каждого каталога в списке дает вам список, состоящий из количества файлов в каждом каталоге; если в каждой есть 7, это дает 3 строки, каждая из которых состоит из числа 7
  • Трубопровод, который через uniq удаляет последовательные повторяющиеся строки.
  • Трубопровод , который с по wc -l дает вам количество отдельных строк, которое будет равно 1, если и только если все каталоги содержат одинаковое количество файлов.

Обратите внимание, что выходные данные 4-го этапа не обязательно дают вам количество различного количества файлов в каталогах; uniq удаляет только смежные дубликаты, поэтому, если входы 7 6 7, два 7 не будут объединены. Но он объединит все строки в 1 только , если они все одинаковые.

В этом сила командной строки Unix: собирать вместе небольшие инструменты, чтобы делать интересные и полезные вещи. (Покажите мне графический интерфейс, который может это сделать!)

Для значений, хранящихся в переменных, заменить первую строку на:

distinct_values=$(echo "$this_var" "$that_var" "$another_var" | fmt -1 | uniq | wc -l)

Предполагается, что значения переменных не содержат пробелов.

1 голос
/ 11 января 2012

(отредактировано, чтобы включить разделители, чтобы исправить проблему, отмеченную Китом Томпсоном)

Обрабатывая значения переменных как строки, вы можете объединить их вместе с подходящим разделителем и сделать одно сравнение:

if [[ "$var1|$var2|$var3" = "$var1|$var1|$var1" ]]

Я использовал = вместо ==, потому что == это не сравнение равенства внутри [[]], это совпадение с шаблоном.

...