On Fri, Aug 07, 2015 at 10:00:53AM +0200, Juanma wrote: > El Thu 6 of Aug, Greg Wooledge profirió estas palabras: > > I believe you are talking about the section that discusses the [[ ... ]] > > command. > > Yes, you are right. And I mean, concretely, the last part: > | Expressions may be combined using the following operators, listed in > decreasing order of precedence: > | ( expression ) > | Returns the value of expression. This may be used to override the normal > precedence of operators. > | ... > > > Point 1: I truly have no idea what you mean. What brackets are you > > escaping, and how, and why? > > Those brackets I cited above: ( expression )
In the US we call those "parentheses", and we reserve the word "brackets" (or "square brackets") for [ ]. I realize that the UK uses different terminology. Hence, the word is ambiguous and you should always type the actual characters you mean. > But I have to apologize because I have just realized that, while still being > a shell issue, it isn't a [[ issue: it's an issue with [. > > [ 'a' == "b" -o 1 -lt 2 -a 1 -gt 0 ] => return 1 > > [ ( 'a' == "b" -o 1 -lt 2 ) -a 1 -gt 0 ] > bash: syntax error near unexpected token `'a'' > > [ \( 'a' == "b" -o 1 -lt 2 \) -a 1 -gt 0 ] => return 0 > > That's the escaping I meant. Yes, the [ and [[ commands have totally different syntax. This is confusing and unfortunate. You just have to live with it. [[ is a "shell keyword" which means that it has special parsing rules that don't apply to ordinary commands. Among other things, you can use shell metacharacters like ( and && inside [[ without escaping them. [ is an ordinary command (a "shell builtin"), so it has no special parsing rules. Arguments to [ have to be escaped or quoted, exactly the same way you would have to escape or quote them if you were passing them to expr(1) or find(1). > > Point 2: Spaces. > [...] > > The manual doesn't explicitly point out that you need spaces after "if" > > or "case". (It fails to mention that you can *omit* the spaces in the > > ((...)) command, but that's a special exception.) > > The thing with brackets is that they are operators (if I'm not wrong), but > they need special treatment, compared to other operators: first, because they > need escaping; second, because they need spaces around them, as if they were > commands or operands: > > [ \('a' == "b" -o 1 -lt 2\) -a 1 -gt 0 ] > bash: [: 2): integer expression expected P.S. == is not required to be supported by the [ command. You should use = instead. Supporting == in [ is a bash extension. > However, it seems like the quotes around a prevent the ambiguity in the case > of the opening bracket: \('a' That causes no error. > > Am I making any point now? You were reading the section on [[ and assuming that it applies to [. That's a huge mistake. (It also didn't help that you talked about escaping "brackets" when the command name in question is two brackets. But you apparently meant inner ( ) arguments within the command.) Many bash users recommend ONLY using [[ and abandoning [ altogether. (I actually disagree, and I often prefer using the portable syntax when it can do what's needed. But you'll have to decide for yourself.) If you choose to use [ then you should use it in a portable way (otherwise, there is no point). And the first thing you need to know about using [ portably is that you CANNOT use -a or -o ("and" or "or") operators in it. Don't even try! Once you get that out of your head, then you don't need parentheses ("UK brackets") either. POSIX says that the behavior of [ depends on how many arguments you pass to it. It has very limited capability. Here's the documentation: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html Basically, almost any expression involving any combination of tests is unspecified. You just can't combine them in a single test or [ command. What you should do instead is use multiple test or [ commands. if test "$a" = foo && test -s "$outputfile" ; then ... fi if [ ! -d "$dir1" ] || [ ! -d "$dir2" ] ; then ... fi That is how you write compound conditional expressions using portable POSIX sh syntax (with the [ or test commands). If you choose to use [[ (a bash extension, also found in ksh) then the rules are entirely different. Within [[ you can join compound expressions using && and ||. if [[ ! -d $dir1 || ! -d $dir2 ]] ; then ... fi Do not use -a or -o. They might as well not EXIST. Just forget them. You can't use them in [ and you can't use them in test and you can't use them in [[. Use one of the syntaxes I've shown here.