Bash: Why does this Brace Expression work this way

bashbrace-expansion

this is a bash 4 specific question. I am somewhat familiar with the bash Brace Expressions and I have read the manual but I do not understand how it actually works.

I guess it has to do with the ASCII table but I am not used to searching the bash source code to confirm it so my question is this:

Why does this echo {G..a} expand to

G H I J K L M N O P Q R S T U V W X Y Z [  ] ^ _ ` a

Best Answer

From the bash manual (with my emphasis):

A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters, and incr, an optional increment, is an integer. When integers are supplied, the expression expands to each number between x and y, inclusive. Supplied integers may be prefixed with 0 to force each term to have the same width. When either x or y begins with a zero, the shell attempts to force all generated terms to contain the same number of digits, zero-padding where necessary. When characters are supplied, the expression expands to each character lexicographically between x and y, inclusive, using the default C locale. Note that both x and y must be of the same type. When the increment is supplied, it is used as the difference between each term. The default increment is 1 or -1 as appropriate.

Brace expansions with letters as ranges allows for mixed-case ranges in bash. So what you are seeing are the characters between G and a in the ASCII table (with a default 1 increment as the values occur in that order in the table).

Between the last uppercase character (Z) and the first lowercase character (a) in the standard ASCII table, there are the characters

[ \ ] ^ _ `

in this order.

You do not get \ in your output as the shell would treat an escaped space character as a literal space. Also note that since an unquoted backtick is outputted, this could potentially lead to unexpected code execution, as pointed out by Stéphane in a message to the bug-bash mailing list in 2015.

I do however not quite know what the manual refers to as "type", but my guess would be that you can't use a letter and a digit, as in {1..z} (which indeed does not expand).

Related Question