Bash: Why does this Brace Expression work this way?
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
add a comment |
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
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
add a comment |
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
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
bash brace-expansion
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
From the bash
manual (with my emphasis):
A sequence expression takes the form
{x..y[..incr]}
, wherex
andy
are
either integers or single characters, andincr
, an optional increment,
is an integer. When integers are supplied, the expression expands to
each number betweenx
andy
, inclusive. Supplied integers may be
prefixed with0
to force each term to have the same width. When either
x
ory
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 betweenx
andy
, inclusive, using the
default C locale. Note that bothx
andy
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).
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
|
show 2 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
From the bash
manual (with my emphasis):
A sequence expression takes the form
{x..y[..incr]}
, wherex
andy
are
either integers or single characters, andincr
, an optional increment,
is an integer. When integers are supplied, the expression expands to
each number betweenx
andy
, inclusive. Supplied integers may be
prefixed with0
to force each term to have the same width. When either
x
ory
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 betweenx
andy
, inclusive, using the
default C locale. Note that bothx
andy
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).
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
|
show 2 more comments
From the bash
manual (with my emphasis):
A sequence expression takes the form
{x..y[..incr]}
, wherex
andy
are
either integers or single characters, andincr
, an optional increment,
is an integer. When integers are supplied, the expression expands to
each number betweenx
andy
, inclusive. Supplied integers may be
prefixed with0
to force each term to have the same width. When either
x
ory
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 betweenx
andy
, inclusive, using the
default C locale. Note that bothx
andy
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).
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
|
show 2 more comments
From the bash
manual (with my emphasis):
A sequence expression takes the form
{x..y[..incr]}
, wherex
andy
are
either integers or single characters, andincr
, an optional increment,
is an integer. When integers are supplied, the expression expands to
each number betweenx
andy
, inclusive. Supplied integers may be
prefixed with0
to force each term to have the same width. When either
x
ory
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 betweenx
andy
, inclusive, using the
default C locale. Note that bothx
andy
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).
From the bash
manual (with my emphasis):
A sequence expression takes the form
{x..y[..incr]}
, wherex
andy
are
either integers or single characters, andincr
, an optional increment,
is an integer. When integers are supplied, the expression expands to
each number betweenx
andy
, inclusive. Supplied integers may be
prefixed with0
to force each term to have the same width. When either
x
ory
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 betweenx
andy
, inclusive, using the
default C locale. Note that bothx
andy
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).
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
|
show 2 more comments
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
|
show 2 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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