是双方括号内的[[]]最好在单一的方括号[]中的庆典?
-
21-08-2019 - |
题
一个共同工作人员声称最近在码的审查, [[ ]]
建构是可以优先选 [ ]
在像构造
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
他不能提供理由。是有一个吗?
解决方案
[[
有减少惊喜和一般使用更安全。但它不是便携式-POSIX不指定用它做什么,只有一些贝壳的支持(旁边的庆典,我听到些支持它太)。例如,你可以做的
[[ -e $b ]]
要测试一个文件是否存在。但与 [
, 你有的话 $b
, ,因为它分割的论点和扩大的东西喜欢 "a*"
(在那里 [[
把它从字面上).这也与如何 [
可能是一个外部程序和接收其参数通常只是喜欢每一个其他程序(虽然它也可以是一个内建的,但它仍然没有这个特殊的处理)。
[[
还有其他一些不错的功能,像经常表达的匹配 =~
随着经营者象他们是已知的在C-喜欢的语言。这里是一个良好的网页: 之间的区别是什么测试 [
和 [[
? 和 砸向试验
其他提示
行为差异
一些差异在Bash4.3.11:
POSIX vs Bash扩展:
[
是POSIX[[
是砸extension1记录: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs
常规命令vs魔法
[
是只是一个普通的命令有一个奇怪的名字。]
只是一个说法的[
这可以防止进一步的辩论正在被使用。Ubuntu的16.04实际上具有可执行它在
/usr/bin/[
提供下载管理器,各种文件下载,但bash建版本优先。没有什么改变的方式,庆典分析的命令。
特别是,
<
正重定向&&
和||
连接的多个命令,( )
生子shell,除非通过逃脱的\
, 和word膨胀发生的一切如常。[[ X ]]
是一个单一的结构,使得X
分析神奇。<
,&&
,||
和()
是经过特殊处理,并字分裂的规则是不同的。还有进一步的差异样
=
和=~
.在Bashese:
[
是一个内置命令,和[[
是一个关键词: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
:词比较[ a \< b ]
:上述相同。\
需要或者不重新定向,像任何其他命令。Bash扩展。expr a \< b > /dev/null
:POSIX equivalent2,参见: 如何测试串字典式小于或等于在庆典?
&&
和||
[[ a = a && b = b ]]
:真的,逻辑 和[ a = a && b = b ]
:语法错误,&&
分析为一个和分隔的命令cmd1 && cmd2
[ a = a -a b = b ]
:相当,但deprecated通过POSIX3[ a = a ] && [ b = b ]
:POSIX和相当可靠
(
[[ (a = a || a = b) && a = b ]]
:假[ ( a = a ) ]
:语法错误,()
是解释为子shell[ \( a = a -o a = b \) -a a = b ]
:相当,但()
是废弃的POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX equivalent⁵
字分割和文件的生成应扩展(分+glob)
x='a b'; [[ $x = 'a b' ]]
:真的,报价不需要x='a b'; [ $x = 'a b' ]
:语法错误,扩大到[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
:语法错误,如果有多于一个文件在当前的目录。x='a b'; [ "$x" = 'a b' ]
:POSIX等
=
[[ ab = a? ]]
:真的,因为它不会 模式匹配 (* ? [
是魔术).不glob扩大到文件在当前的目录。[ ab = a? ]
:a?
glob扩大。所以可能是真实的或虚假的,根据该文件,在当前的目录。[ ab = a\? ]
:假,不glob膨胀=
和==
是同在这两个[
和[[
, 但==
是砸扩展。case ab in (a?) echo match; esac
:POSIX等[[ ab =~ 'ab?' ]]
:false⁴,失去魔法''
[[ ab? =~ 'ab?' ]]
:真的
=~
[[ ab =~ ab? ]]
:真的,POSIX 延长经常表达 匹配,?
不扩大滴[ a =~ a ]
:语法错误。没有庆典等同的。printf 'ab\n' | grep -Eq 'ab?'
:POSIX当量(单线数据)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
:POSIX等同的。
建议:总是用 []
.
有POSIX当量为每 [[ ]]
建造我见过的。
如果你使用 [[ ]]
你:
- 失去可携带性
- 迫使读者了解错综复杂的另一个bash扩展。
[
是只是一个普通的命令有一个奇怪的名字,没有特殊的语义的参与。
1的启发,从相当于 [[...]]
建造在Korn壳
2但是失败对于有些价值观的 a
或 b
(喜欢 +
或 index
)并不比较数字如果 a
和 b
看起来像小数整数。 expr "x$a" '<' "x$b"
工作围绕两个。
3和也失败对于有些价值观的 a
或 b
喜欢 !
或 (
.
原生在bash3.2和上述和提供的兼容性来砸3.1未启用(如与 BASH_COMPAT=3.1
)
⁵虽然分组(这里的 {...;}
命令组,而不是的 (...)
这将运行的不必要的子shell)是不必要的,因为 ||
和 &&
壳运营商(而不是的 ||
和 &&
[[...]]
经营者或 -o
/-a
[
经营者)拥有同等优先。所以 [ a = a ] || [ a = b ] && [ a = b ]
会是同等的。
[[ ]]
具有更多的功能 - 我建议你去看看高级Bash脚本编程指南更多的信息,特别是 扩展测试命令 在第7章测试部分。
顺便提及,作为引导记录,[[ ]]
在ksh88(1988年版Korn外壳的)。
从 其中比较器、测试、支架或双架,是最快? (http://bashcurescancer.com)
双架是一个"复合 命令"作为测试和单 支架是外壳内置程序(在 实际上是相同的命令)。因此, 这个支架和双重支架 执行不同的代码。
测试和单个支架是 最便携式,因为他们的存在 独立和外部的命令。然而,如果您使用的任何远程 现代版的庆典,双 支架支持。
在这里你不能使用[典型的情况是在自动工具configure.ac脚本,有括号具有特殊和不同的意义,所以你将不得不使用test
代替[或[ - 请注意,测试和[是相同的程序。
如果你到以下 谷歌的风格指导:
试验,[并[[
[[...]]减少错误,因为没有路径扩展字或分裂之间发生[[和]]和[[...]]允许为经常表达的匹配,其中[... 不不是。
# This ensures the string on the left is made up of characters in the
# alnum character class followed by the string name.
# Note that the RHS should not be quoted here.
# For the gory details, see
# E14 at https://tiswww.case.edu/php/chet/bash/FAQ
if [[ "filename" =~ ^[[:alnum:]]+name ]]; then
echo "Match"
fi
# This matches the exact pattern "f*" (Does not match in this case)
if [[ "filename" == "f*" ]]; then
echo "Match"
fi
# This gives a "too many arguments" error as f* is expanded to the
# contents of the current directory
if [ "filename" == f* ]; then
echo "Match"
fi
[[]]双括号是某些版本的SunOS和通过完全不支持的内部函数声明的下不受支持: GNU bash中,版本2.02.0(1)-release(Sun SPARC的-solaris2.6)
概括地说,[[比较好,因为它不会叉的另一过程。没有括号或单个托架比双托架,因为它fork另一个进程慢。