1 #!/bin/bash
2
3 ### [[ glob matching, [[ has no glob expansion
4 [[ foo.py == *.py ]] && echo true
5 [[ foo.p == *.py ]] || echo false
6 # stdout-json: "true\nfalse\n"
7
8 ### [[ glob matching with escapes
9 [[ 'foo.*' == *."*" ]] && echo true
10 # note that the pattern arg to fnmatch should be '*.\*'
11 # stdout: true
12
13 ### equality
14 [[ '*.py' == '*.py' ]] && echo true
15 [[ foo.py == '*.py' ]] || echo false
16 # stdout-json: "true\nfalse\n"
17
18 ### [[ glob matching with unquoted var
19 pat=*.py
20 [[ foo.py == $pat ]] && echo true
21 [[ foo.p == $pat ]] || echo false
22 # stdout-json: "true\nfalse\n"
23
24 ### [[ regex matching
25 # mksh doesn't have this syntax of regex matching. I guess it comes from perl?
26 regex='.*\.py'
27 [[ foo.py =~ $regex ]] && echo true
28 [[ foo.p =~ $regex ]] || echo false
29 # stdout-json: "true\nfalse\n"
30 # N-I mksh stdout-json: ""
31 # N-I mksh status: 1
32
33 ### [[ regex syntax error
34 # hm, it doesn't show any error, but it exits 2.
35 [[ foo.py =~ * ]] && echo true
36 # status: 2
37 # N-I mksh status: 1
38
39 ### [[ has no word splitting
40 var='one two'
41 [[ 'one two' == $var ]] && echo true
42 # stdout: true
43
44 ### [[ has quote joining
45 var='one two'
46 [[ 'one 'tw"o" == $var ]] && echo true
47 # stdout: true
48
49 ### [[ empty string is false
50 [[ 'a' ]] && echo true
51 [[ '' ]] || echo false
52 # stdout-json: "true\nfalse\n"
53
54 ### && chain
55 [[ t && t && '' ]] || echo false
56 # stdout: false
57
58 ### || chain
59 [[ '' || '' || t ]] && echo true
60 # stdout: true
61
62 ### [[ compound expressions
63 # Notes on whitespace:
64 # - 1 and == need space seprating them, but ! and ( don't.
65 # - [[ needs whitesapce after it, but ]] doesn't need whitespace before it!
66 [[ ''||!(1 == 2)&&(2 == 2)]] && echo true
67 # stdout: true
68
69 # NOTE on the two cases below. We're comparing
70 # (a || b) && c vs. a || (b && c)
71 #
72 # a = true, b = false, c = false is an example where they are different.
73 # && and || have precedence inside
74
75 ### precedence of && and || inside [[
76 [[ True || '' && '' ]] && echo true
77 # stdout: true
78
79 ### precedence of && and || in a command context
80 if test True || test '' && test ''; then
81 echo YES
82 else
83 echo "NO precedence"
84 fi
85 # stdout: NO precedence
86
87 # http://tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS
88
89 ### Octal literals with -eq
90 decimal=15
91 octal=017 # = 15 (decimal)
92 [[ $decimal -eq $octal ]] && echo true
93 [[ $decimal -eq ZZZ$octal ]] || echo false
94 # stdout-json: "true\nfalse\n"
95 # N-I mksh stdout: false
96 # mksh doesn't implement this syntax for literals.
97
98 ### Hex literals with -eq
99 decimal=15
100 hex=0x0f # = 15 (decimal)
101 [[ $decimal -eq $hex ]] && echo true
102 [[ $decimal -eq ZZZ$hex ]] || echo false
103 # stdout-json: "true\nfalse\n"
104 # N-I mksh stdout: false
105
106 # TODO: Add tests for this
107 # https://www.gnu.org/software/bash/manual/bash.html#Bash-Conditional-Expressions
108 # When used with [[, the ‘<’ and ‘>’ operators sort lexicographically using the current locale. The test command uses ASCII ordering.
109
110 ### > on strings
111 # NOTE: < doesn't need space, even though == does? That's silly.
112 [[ b>a ]] && echo true
113 [[ b<a ]] || echo false
114 # stdout-json: "true\nfalse\n"
115
116 ### != on strings
117 # NOTE: b!=a does NOT work
118 [[ b != a ]] && echo true
119 [[ a != a ]] || echo false
120 # stdout-json: "true\nfalse\n"
121
122 ### -eq on strings
123 # This is lame behavior: it does a conversion to 0 first for any string
124 [[ a -eq a ]] && echo true
125 [[ a -eq b ]] && echo true
126 # stdout-json: "true\ntrue\n"
127 # OK bash/mksh stdout-json: "true\ntrue\n"
128
129 ### [[ compare with literal -f
130 var=-f
131 [[ $var == -f ]] && echo true
132 [[ '-f' == $var ]] && echo true
133 # stdout-json: "true\ntrue\n"
134
135 ### [ compare with literal -f
136 # Hm this is the same
137 var=-f
138 [ $var == -f ] && echo true
139 [ '-f' == $var ] && echo true
140 # stdout-json: "true\ntrue\n"
141
142 ### [[ with op variable
143 # Parse error -- parsed BEFORE evaluation of vars
144 op='=='
145 [[ a $op a ]] && echo true
146 [[ a $op b ]] || echo false
147 # status: 2
148 # OK mksh status: 1
149
150 ### [ with op variable
151 # OK -- parsed AFTER evaluation of vars
152 op='=='
153 [ a $op a ] && echo true
154 [ a $op b ] || echo false
155 # status: 0
156 # stdout-json: "true\nfalse\n"
157
158 ### [[ with unquoted empty var
159 empty=''
160 [[ $empty == '' ]] && echo true
161 # stdout: true
162
163 ### [ with unquoted empty var
164 empty=''
165 [ $empty == '' ] && echo true
166 # status: 2
167
168 ### [[ at runtime doesn't work
169 dbracket=[[
170 $dbracket foo == foo ]]
171 # status: 127
172
173 ### [[ with env prefix doesn't work
174 FOO=bar [[ foo == foo ]]
175 # status: 127
176
177 ### [[ over multiple lines is OK
178 # Hm it seems you can't split anywhere?
179 [[ foo == foo
180 && bar == bar
181 ]] && echo true
182 # status: 0
183 # stdout-json: "true\n"
184
185 ### Argument that looks like a command word operator
186 [[ -f -f ]] || echo false
187 [[ -f == ]] || echo false
188 # stdout-json: "false\nfalse\n"
189
190 ### Argument that looks like a real operator
191 [[ -f < ]]
192 # status: 2
193 # OK mksh status: 1
194
195 ### Does user array equal "$@" ?
196 # Oh it coerces both to a string. Lame.
197 # I think it disobeys "${a[@]}", and treats it like an UNQUOTED ${a[@]}.
198 a=(1 3 5)
199 b=(1 2 3)
200 set -- 1 3 5
201 [[ "$@" = "${a[@]}" ]] && echo true
202 [[ "$@" = "${b[@]}" ]] || echo false
203 # stdout-json: "true\nfalse\n"
204
205 ### Array coerces to string
206 a=(1 3 5)
207 [[ '1 3 5' = "${a[@]}" ]] && echo true
208 [[ '1 3 4' = "${a[@]}" ]] || echo false
209 # stdout-json: "true\nfalse\n"
210
211 ### Quotes don't matter in comparison
212 [[ '3' = 3 ]] && echo true
213 [[ '3' -eq 3 ]] && echo true
214 # stdout-json: "true\ntrue\n"