[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Worth mentioning in documentation
From: |
Greg Wooledge |
Subject: |
Re: Worth mentioning in documentation |
Date: |
Fri, 7 Aug 2015 08:24:54 -0400 |
User-agent: |
Mutt/1.4.2.3i |
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.
- Worth mentioning in documentation, Juanma, 2015/08/06
- Re: Worth mentioning in documentation, Greg Wooledge, 2015/08/06
- Message not available
- Re: Worth mentioning in documentation,
Greg Wooledge <=
- Re: Worth mentioning in documentation, Eduardo A . Bustamante López, 2015/08/07
- Re: Worth mentioning in documentation, Juanma, 2015/08/10
- Re: Worth mentioning in documentation, Greg Wooledge, 2015/08/10
- Re: Worth mentioning in documentation, Bob Proulx, 2015/08/10
- Re: Worth mentioning in documentation, Juanma, 2015/08/11
- Re: Worth mentioning in documentation, Eric Blake, 2015/08/10