LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 06-04-2013, 09:12 AM   #1
CelticFiddler
LQ Newbie
 
Registered: Aug 2012
Location: Grand Prairie, TX
Distribution: Ubuntu (mostly), CentOS (when I have to)
Posts: 12

Rep: Reputation: Disabled
bash question on nested braces


I was reading through the latest edition of Linux Programming Unleased. On page 717, the author gives an example:
Code:
$ echo c{ar,at,an}s
which results in: cars cats cans

That works on my Ubuntu system (bash 4.2.25(1)-release) exactly as the example states.

However, the author then says that since braces can be nested, the command:
Code:
$ echo c{a{r,t,n}}s
should produce the same output. But on my system, the output is:

c{ar}s c{at}s c{an}s

Is this a bash bug?

I get the expected output for the following command:
Code:
echo c{a{r,t},an}s
and also:
Code:
echo c{a{r,t,},a{b,n}}
so is output for the case c{a{r,t,n}}s a bug, or a subtle exception?

Last edited by CelticFiddler; 06-04-2013 at 09:28 AM. Reason: code tags
 
Old 06-04-2013, 09:43 AM   #2
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,008

Rep: Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193
You probably have to wait for David.H to look at this, but I believe it is a subtle exception. The exception being that without a comma separated list the braces are interpreted literally.

I found this by doing the following:
Code:
$ echo c{a{r,t,n},}s
cars cats cans cs
So as the man page says, {} is used to denote a list, so with the absence of a list I would guess it reverts to literal braces:
Code:
{ list; }
              list is simply executed in the current shell environment.  list must be terminated with a newline or semicolon.  This is known as a group command.  The return status is the exit status of list.  Note that  unlike  the
              metacharacters  (  and ), { and } are reserved words and must occur where a reserved word is permitted to be recognized.  Since they do not cause a word break, they must be separated from list by whitespace or another
              shell metacharacter.
 
Old 06-04-2013, 10:04 AM   #3
Beryllos
Member
 
Registered: Apr 2013
Location: Massachusetts
Distribution: Debian
Posts: 529

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
There must be at least one comma or sequence expression.

Quote:
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression. Any incorrectly formed brace expansion is left unchanged.
That is from http://www.gnu.org/software/bash/man...Expansion.html
I added the bold highlighting.

So you see that without a comma in your example, it is considered an "incorrectly formed brace expansion" and is "left unchanged."

Last edited by Beryllos; 06-04-2013 at 10:12 AM.
 
Old 06-04-2013, 02:27 PM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Perhaps the code above does work in some other shell like zsh?

But I think Beryllos has found the key to it in bash. A brace expansion can only be used inside another if it's completely contained inside a list sub-entry. It looks like your book is wrong.

It appears that bash is reading it with the following three parts, with only the middle part being a valid brace expansion:
Code:
c{a        #beginning string
{r,t,n}    #brace expansion
}s         #ending string
The last two expansions work because they break down this way:

Code:
echo c{a{r,t},an}s
c        #beginning string
{        #main brace expansion start
a{r,t}   #first element (nested expansion)
,        #list separator
an       #second element
}        #main brace expansion end
s        #ending string

echo c{a{r,t,},a{b,n}}
c        #beginning string
{        #main brace expansion start
a{r,t,}  #first element (nested expansion)
,        #list separator
a{b,n}   #second element (nested expansion)
}        #main brace expansion end
Nested expansions can be quite a headache.

I've found the bash-hacker's page on it to be quite useful.
http://wiki.bash-hackers.org/syntax/expansion/brace
 
Old 06-04-2013, 02:56 PM   #5
Madhu Desai
Member
 
Registered: Mar 2013
Distribution: Rocky, Fedora, Ubuntu
Posts: 541

Rep: Reputation: 153Reputation: 153
This is what i got. it wont work in bash shell...

Code:
$ echo $0
/bin/bash

$ echo c{a{r,t,n}}s
c{ar}s c{at}s c{an}s

$ /bin/sh
sh-4.1$ echo c{a{r,t,n}}s
c{ar}s c{at}s c{an}s

sh-4.1$ /bin/dash
$ echo c{a{r,t,n}}s
c{a{r,t,n}}s

$ /bin/tcsh
$ echo c{a{r,t,n}}s
cars cats cans

$ /bin/csh
$ echo c{a{r,t,n}}s
cars cats cans
 
Old 06-04-2013, 03:24 PM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Brace expansion is only available in some advanced shells like bash, ksh, and probably zsh. It won't work in strictly posix-based shells like dash.

/bin/sh is your system's posix-supporting shell, which is usually a symlink to another interpreter like bash or dash. So it may work or it may not, depending on what that link is.

And we've already explained the problems with the above line in bash (it does work, it just doesn't work as expected by the OP).

But it is interesting to see that it apparently also works in c-shell environments, and apparently works as expected.

Last edited by David the H.; 06-04-2013 at 03:28 PM.
 
Old 06-05-2013, 10:23 AM   #7
Kenhelm
Member
 
Registered: Mar 2008
Location: N. W. England
Distribution: Mandriva
Posts: 360

Rep: Reputation: 170Reputation: 170
The book is correct for old versions of bash.
Bash started to behave differently somewhere around the introduction of version 4.
Code:
echo c{a{r,t,n}}s

cars cats cans          # bash 2.05b.0(1)
cars cats cans          # bash 3.1.17(2)
c{ar}s c{at}s c{an}s    # bash 4.1.5(2)
c{ar}s c{at}s c{an}s    # bash 4.2.37(2)
 
2 members found this post helpful.
Old 06-06-2013, 12:54 PM   #8
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Even more interesting stuff to learn! I guess bash originally tried to emulate the csh style, but later went its own way for some reason.

Incidentally, I made an error in my last post. Posix does have the "{a,b,c}" list style of expansion, but it does not support the "{a..z}" range style.
 
Old 06-29-2022, 09:16 AM   #9
CelticFiddler
LQ Newbie
 
Registered: Aug 2012
Location: Grand Prairie, TX
Distribution: Ubuntu (mostly), CentOS (when I have to)
Posts: 12

Original Poster
Rep: Reputation: Disabled
Works in bash 4.3.48

I revisited this today, and tried
Code:
echo c{a{r,t,n}}s
and got the output
Code:
cars cats cans
...so it appears that this is version-dependent.
 
Old 06-30-2022, 04:57 AM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,008

Rep: Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193
Still the same for version 5.1.16
Code:
30-06-2022 17:56:07][~]
[grail@killrazor]$ echo c{a{r,t,n}}s
c{ar}s c{at}s c{an}s
 
Old 06-30-2022, 06:40 AM   #11
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,927

Rep: Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320Reputation: 7320
Quote:
Originally Posted by CelticFiddler View Post
I revisited this today, and tried
Code:
echo c{a{r,t,n}}s
and got the output
Code:
cars cats cans
...so it appears that this is version-dependent.
Code:
$ echo c{a{r,t,n}}s
c{ar}s c{at}s c{an}s
$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
 
Old 06-30-2022, 07:32 AM   #12
boughtonp
Senior Member
 
Registered: Feb 2007
Location: UK
Distribution: Debian
Posts: 3,616

Rep: Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554Reputation: 2554

To reiterate what was stated in post #3 from June 2013 this behaviour is clearly described in the Brace Expansion documentation:

Quote:
Originally Posted by https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html
Brace expansions may be nested.
...
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression. Any incorrectly formed brace expansion is left unchanged.
Without a comma, and without a sequence expression {INTEGER..INTEGER}, the outer expansion is incorrectly formed and thus should be left unchanged.

If someone feels they have found a bug in a supported version of Bash, they should report it to GNU on the Bash bug mailing list, though I'm not sure 4.3 is supported.

 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] BASH Question - nested case statements jbeiter Linux - Software 2 02-13-2012 10:08 AM
[SOLVED] Bash and nested read commands fransdb Linux - Software 1 04-05-2010 03:55 PM
nested , piped bash commands nass Programming 9 06-17-2008 06:33 AM
Unexpected curly braces in expect script spawn command & bash suid problem slinx Programming 1 05-02-2008 01:47 PM
Nested Bash Script downbound010 Programming 1 12-10-2005 02:37 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 04:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration