Bash:测试多个变量的相互相等性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8812089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash: test mutual equality of multiple variables?
提问by reve_etrange
What is the right way to test if several variables are all equal?
测试几个变量是否都相等的正确方法是什么?
if [[ $var1 = $var2 = $var3 ]] # syntax error
Is it necessary to write something like the following?
是否有必要写如下内容?
if [[ $var1 = $var2 && $var1 = $var3 && $var2 = $var3 ]] # cumbersome
if [[ $var1 = $var2 && $var2 = $var3 && $var3 = $var4 ]] # somewhat better
Unfortunately, the otherwise excellent Advanced Bash Scripting Guideand other online sources I could find don't provide such an example.
不幸的是,我能找到的其他优秀的Advanced Bash Scripting Guide和其他在线资源没有提供这样的例子。
My particular motivation is to test if several directories all have the same number of files, using ls -1 $dir | wc -lto count files.
我的特别动机是测试几个目录是否都具有相同数量的文件,ls -1 $dir | wc -l用于对文件进行计数。
Note
"var1" etc. are example variables. I'm looking for a solution for arbitrary variable names, not just those with a predictable numeric ending.
注意
“var1”等是示例变量。我正在寻找任意变量名称的解决方案,而不仅仅是那些具有可预测数字结尾的解决方案。
Update
I've accepted Richo's answer, as it is the most general. However, I'm actually using Kyle's because it's the simplest and my inputs are guaranteed to avoid the caveat.
更新
我接受了 Richo 的回答,因为它是最通用的。然而,我实际上使用的是 Kyle 的,因为它是最简单的,而且我的输入可以保证避免警告。
Thanks for the suggestions, everyone.
谢谢大家的建议。
回答by richo
if you want to test equality of an arbitrary number of items (let's call them $item1-5, but they could be an array
如果你想测试任意数量的项目的相等性(我们称它们为 $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
回答by jim
If they are single words you can get really cheap about it.
如果它们是单个词,你会很便宜。
varUniqCount=`echo "${var1} ${var2} ${var3} ${var4}" | sort -u | wc -l`
if [ ${varUniqCount} -gt 1 ]; then
echo "Do not match"
fi
回答by Kyle Jones
(edited to include delimiters to fix the problem noted by Keith Thompson)
(编辑以包含定界符以解决 Keith Thompson 指出的问题)
Treating the variable values as strings, you can concatenate them along with a suitable delimiter and do one comparison:
将变量值视为字符串,您可以将它们与合适的分隔符连接起来并进行比较:
if [[ "$var1|$var2|$var3" = "$var1|$var1|$var1" ]]
I used = instead == because == isn't an equality comparison inside [[ ]], it is a pattern match.
我使用 = 代替 == 因为 == 不是 [[ ]] 内的相等比较,它是模式匹配。
回答by jaypal singh
Transitive methodof inspection.
传递性检查方法。
#!/bin/bash
var1=10
var2=10
var3=10
if [[ ($var1 == $var2) && ($var2 == $var3) ]]; then
echo "yay"
else
echo "nay"
fi
Output:
输出:
[jaypal:~/Temp] ./s.sh
yay
Note:
笔记:
Since you have stated in your question that your objective is to test several directories that have same number of files, I thought of the following solution. I know this isn't something you had request so please feel free to disregard it.
由于您在问题中表示您的目标是测试具有相同文件数的多个目录,因此我想到了以下解决方案。我知道这不是您的要求,所以请随意忽略它。
Step1:
第1步:
Identify number of files in a given directory. This command will look inside sub-dirs too but that can be controlled using -depthoption of find.
确定给定目录中的文件数。此命令将往里子迪尔斯太多,但可以使用进行控制-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:
第2步:
This can be combined with Step1as we are just redirecting the content to a file.
这可以结合使用,Step1因为我们只是将内容重定向到文件。
[jaypal:~/Temp] find . -type d -exec sh -c "printf {} && ls -1 {} | wc -l " \; > file.temp
Step3:
第三步:
Using the following command we will look in the file.temp twice and it will give us a list of directories that have same number of files.
使用以下命令,我们将查看 file.temp 两次,它将为我们提供具有相同文件数的目录列表。
[jaypal:~/Temp] awk 'NR==FNR && a[]++ {b[];next} ( 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
回答by Keith Thompson
For your specific case, this should work:
对于您的具体情况,这应该有效:
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
Explanation:
解释:
ls -l "$dir"lists the files and subdirectories in the directory, one per line (omitting dot files).- Piping the output through
wc -lgives you the number of files in the directory. - Doing that consecutively for each directory in the list gives you a list consisting of the number of files in each directory; if there are 7 in each, this gives 3 lines each consisting of the number
7 - Piping that through
uniqeliminates consecutive duplicate lines. - Piping thatthrough
wc -lgives you the number of distinct lines, which will be 1 if and only if all the directories contain the same number of files.
ls -l "$dir"列出目录中的文件和子目录,每行一个(省略点文件)。- 通过管道输出可以
wc -l为您提供目录中的文件数。 - 对列表中的每个目录连续执行此操作会为您提供一个由每个目录中的文件数组成的列表;如果每个都有 7,这将给出 3 行,每行由数字组成
7 - 管道通过
uniq消除连续的重复行。 - 管道是通过
wc -l给你的不同线路的数量,这将是1当且仅当所有的目录包含相同数量的文件。
Note that the output of the 4th stage doesn't necessarily give you the number of distinct numbers of files in the directories; uniqonly removes adjacentduplicates, so if the inputs are 7 6 7, the two 7s won't be merged. But it will merge all lines into 1 onlyif they're all the same.
请注意,第 4 阶段的输出不一定会为您提供目录中不同数量的文件的数量;uniq只删除相邻的重复项,因此如果输入是7 6 7,则两个7s 不会合并。但只有当它们都相同时,它才会将所有行合并为 1 。
This is the power of the Unix command line: putting small tools together to do interesting and useful things. (Show me a GUI that can do that!)
这就是 Unix 命令行的强大之处:将小工具放在一起来做有趣和有用的事情。(给我看一个可以做到这一点的 GUI!)
For values stored in variables, replace the first line by:
对于存储在变量中的值,将第一行替换为:
distinct_values=$(echo "$this_var" "$that_var" "$another_var" | fmt -1 | uniq | wc -l)
This assumes that the values of the variables don't contain spaces.
这假设变量的值不包含空格。

