Bash: Why does this Brace Expression work this way?












6















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









share|improve this question

























  • It does not have to be the ASCII table. It depends on your locale.

    – Weijun Zhou
    Mar 20 at 10:50











  • I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

    – Nikolaos Paschos
    Mar 20 at 10:55






  • 1





    Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

    – Nikolaos Paschos
    Mar 20 at 11:19






  • 2





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

    – Stéphane Chazelas
    Mar 20 at 12:02






  • 1





    ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

    – chepner
    Mar 20 at 13:34
















6















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









share|improve this question

























  • It does not have to be the ASCII table. It depends on your locale.

    – Weijun Zhou
    Mar 20 at 10:50











  • I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

    – Nikolaos Paschos
    Mar 20 at 10:55






  • 1





    Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

    – Nikolaos Paschos
    Mar 20 at 11:19






  • 2





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

    – Stéphane Chazelas
    Mar 20 at 12:02






  • 1





    ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

    – chepner
    Mar 20 at 13:34














6












6








6


1






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









share|improve this question
















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






bash brace-expansion






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 20 at 11:19







Nikolaos Paschos

















asked Mar 20 at 10:48









Nikolaos PaschosNikolaos Paschos

355




355













  • It does not have to be the ASCII table. It depends on your locale.

    – Weijun Zhou
    Mar 20 at 10:50











  • I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

    – Nikolaos Paschos
    Mar 20 at 10:55






  • 1





    Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

    – Nikolaos Paschos
    Mar 20 at 11:19






  • 2





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

    – Stéphane Chazelas
    Mar 20 at 12:02






  • 1





    ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

    – chepner
    Mar 20 at 13:34



















  • It does not have to be the ASCII table. It depends on your locale.

    – Weijun Zhou
    Mar 20 at 10:50











  • I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

    – Nikolaos Paschos
    Mar 20 at 10:55






  • 1





    Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

    – Nikolaos Paschos
    Mar 20 at 11:19






  • 2





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

    – Stéphane Chazelas
    Mar 20 at 12:02






  • 1





    ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

    – chepner
    Mar 20 at 13:34

















It does not have to be the ASCII table. It depends on your locale.

– Weijun Zhou
Mar 20 at 10:50





It does not have to be the ASCII table. It depends on your locale.

– Weijun Zhou
Mar 20 at 10:50













I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

– Nikolaos Paschos
Mar 20 at 10:55





I guess each charset uses a different ASCII table. My guess is that there is a loop somewhere in the code. The start and end delimiters are encoded in hex or dec and each element is printed with it's printable counterpart. With a different locale I guess one can indeed expect different results. Does this make the brace expressions not portable, even when bash 4 is guaranteed to be used?

– Nikolaos Paschos
Mar 20 at 10:55




1




1





Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

– Nikolaos Paschos
Mar 20 at 11:19





Yeah you are right, if you run echo {G..a} you will get the output I mentioned. I will edit my question, which still remains though.

– Nikolaos Paschos
Mar 20 at 11:19




2




2





See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

– Stéphane Chazelas
Mar 20 at 12:02





See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html (which explains the missing backslash)

– Stéphane Chazelas
Mar 20 at 12:02




1




1





ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

– chepner
Mar 20 at 13:34





ASCII is a charset; if you have a different character set than ASCII, then ASCII tables don't apply.

– chepner
Mar 20 at 13:34










1 Answer
1






active

oldest

votes


















6














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).






share|improve this answer


























  • I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

    – Weijun Zhou
    Mar 20 at 12:01






  • 3





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

    – Stéphane Chazelas
    Mar 20 at 12:03






  • 1





    "Type" seems to refer to integer/char. So {3..z} won't work.

    – Weijun Zhou
    Mar 20 at 12:03











  • @WeijunZhou I just realised :-)

    – Kusalananda
    Mar 20 at 12:06











  • @WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

    – 炸鱼薯条德里克
    Mar 20 at 12:14











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507398%2fbash-why-does-this-brace-expression-work-this-way%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














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).






share|improve this answer


























  • I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

    – Weijun Zhou
    Mar 20 at 12:01






  • 3





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

    – Stéphane Chazelas
    Mar 20 at 12:03






  • 1





    "Type" seems to refer to integer/char. So {3..z} won't work.

    – Weijun Zhou
    Mar 20 at 12:03











  • @WeijunZhou I just realised :-)

    – Kusalananda
    Mar 20 at 12:06











  • @WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

    – 炸鱼薯条德里克
    Mar 20 at 12:14
















6














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).






share|improve this answer


























  • I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

    – Weijun Zhou
    Mar 20 at 12:01






  • 3





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

    – Stéphane Chazelas
    Mar 20 at 12:03






  • 1





    "Type" seems to refer to integer/char. So {3..z} won't work.

    – Weijun Zhou
    Mar 20 at 12:03











  • @WeijunZhou I just realised :-)

    – Kusalananda
    Mar 20 at 12:06











  • @WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

    – 炸鱼薯条德里克
    Mar 20 at 12:14














6












6








6







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).






share|improve this 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).







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 20 at 12:57

























answered Mar 20 at 11:54









KusalanandaKusalananda

137k17258426




137k17258426













  • I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

    – Weijun Zhou
    Mar 20 at 12:01






  • 3





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

    – Stéphane Chazelas
    Mar 20 at 12:03






  • 1





    "Type" seems to refer to integer/char. So {3..z} won't work.

    – Weijun Zhou
    Mar 20 at 12:03











  • @WeijunZhou I just realised :-)

    – Kusalananda
    Mar 20 at 12:06











  • @WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

    – 炸鱼薯条德里克
    Mar 20 at 12:14



















  • I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

    – Weijun Zhou
    Mar 20 at 12:01






  • 3





    See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

    – Stéphane Chazelas
    Mar 20 at 12:03






  • 1





    "Type" seems to refer to integer/char. So {3..z} won't work.

    – Weijun Zhou
    Mar 20 at 12:03











  • @WeijunZhou I just realised :-)

    – Kusalananda
    Mar 20 at 12:06











  • @WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

    – 炸鱼薯条德里克
    Mar 20 at 12:14

















I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

– Weijun Zhou
Mar 20 at 12:01





I didn't know that it is always the C locale. Seems I have mixed it up with [a..z].

– Weijun Zhou
Mar 20 at 12:01




3




3





See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

– Stéphane Chazelas
Mar 20 at 12:03





See also lists.gnu.org/archive/html/bug-bash/2015-07/msg00135.html

– Stéphane Chazelas
Mar 20 at 12:03




1




1





"Type" seems to refer to integer/char. So {3..z} won't work.

– Weijun Zhou
Mar 20 at 12:03





"Type" seems to refer to integer/char. So {3..z} won't work.

– Weijun Zhou
Mar 20 at 12:03













@WeijunZhou I just realised :-)

– Kusalananda
Mar 20 at 12:06





@WeijunZhou I just realised :-)

– Kusalananda
Mar 20 at 12:06













@WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

– 炸鱼薯条德里克
Mar 20 at 12:14





@WeijunZhou So...Bash has the concept "Type" or it just know your string is in "number form" so reject your operation?

– 炸鱼薯条德里克
Mar 20 at 12:14


















draft saved

draft discarded




















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507398%2fbash-why-does-this-brace-expression-work-this-way%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?