[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bash Question



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thu, Jul 06, 2017 at 09:57:50AM +0100, Darac Marjal wrote:
> On Thu, Jul 06, 2017 at 12:22:29AM +0200, Javier Barroso wrote:
> >Hi,
> >
> >On Wed, Jul 5, 2017 at 11:12 PM, Rainer Dorsch <ml@bokomoko.de> wrote:
> >>Hi,
> >>
> >>
> >>
> >>can anybody help to explain what is going on here ?
> >>
> >>
> >>
> >>
> >>
> >>rd@mohot:~$ echo $SHELL
> >>/bin/bash
> >>rd@mohot:~$ if [ "abc" > "dec" ]; then echo bad; fi
> >>bad
> >>rd@mohot:~$ if [ "abc" < "dec" ]; then echo good; fi
> >>good
> >>rd@mohot:~$
> >>
> >>How can abc sort before and after dec at the same time?
> >
> >You need to scape "<" and ">":
> >
> >if [ "abc" \> "dec" ] ; then ... ;fi
> >if [ "abc" '>' "dec" ]; then ... ; fi
> >if [ "abc" ">" "dec" ]; then ... ; fi
> >
> >
> >Delete "dec" file, ( ">" is redirection in bash, so you was creating that file
> 
> That's a very good point. ">" and "<" are NOT the greater-than/less-than
> operators in bash.

They are (in bash: see below!) -- just check bash's manual page under
"conditional expressions".

For strings, they list '==' and '=', '!=', '<' and '>'.

Now *if* you use '[' (single square bracket) as above, you are not using
bash's built in [this is a little white lie[1], see below], but the external
command 'test' or some cousin of that (just try "ls -l /usr/bin/[" to see
what I mean. This one doesn't understand < and >.

If you want bash's builtin, use '[[' (double square bracket). It's faster
(one less fork/exec), but also more convenient, because it "knows" that
there's special syntax inside, so you don't need to escape < and > (as
someone pointed out in this thread, see (again) below).

This works:

  if [[ "abc" < "bcd" ]] ; then  echo "yo" ; else echo "no" ; fi

Or this

  if [[ -n "abc" && ( "abc" < "bcd" ) ]] ; then  echo "yo" ; else echo "no" ; fi

(note I didn't have to escape the parens, which would wreak havoc
elsewhere in the command line, because they have a special meaning
for the shell, and the shell does expansion before calling commands.
Only a builtin can achieve that).

Now try this:

  if [ "abc" < "bcd" ] ; then  echo "yo" ; else echo "no" ; fi

(note I chose '<' -- and hope there's no file 'bcd' lying around).
Then I get:

  bash: bcd: No such file or directory

Now this all was a lie :-)

Or half. The '[' can be a builtin, after all (in bash). You can
switch that on or off with the enable -- uh -- builtin.

Just type "help enable" at your favourite bash instance to learn
about that.

But the '[' builtin has to behave as far as possible like the
/usr/bin/[ of yore (aka POSIX 'test'). Including the way the
shell "expands its innards" before handing things to the command.

That's why there is [[. Much easier to write and much easier on
the eye.

BUT: this all won't work on dash (Debian's preferred non-interactive
shell: much smaller and faster). There you have to spell things like
so:

  if [ "abc" \< "bcd" ] ; then  echo "yo" ; else echo "no" ; fi

So dash's '[' is a builtin too (remember: /usr/bin/[ doesn't grok
'<' at all). But dash hasn't the '[[' with its syntactic convenience.

Hope that helps, somewhat :-)

Cheers
[1] OK, OK. A dirty grey lie. Read on :-)

- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlleB/QACgkQBcgs9XrR2kZQqgCfbCXMBkw2vwJd2xtfqNSc2/bI
NBkAn1MM8uGnehVTxNQWAP07ptBwJSI9
=r8rB
-----END PGP SIGNATURE-----


Reply to: