Create arrays with brace expansion in loop












4















I would like to generate a number of arrays that differ only by year. In the loop, I create the arrays with brace expansion and a variable.



I tried the following code without success:



LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
declare -a 'y$year=('"$LIST"'-$year)'
echo "${y$year[@]}"
done


The outcome should be the list of the following entries:



y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
...
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


I don't need to print them, just use them in a loop as well as pass them as arguments. Because of the second, eval in the loop is not sufficient.










share|improve this question

























  • Why the hardquotes there? I think you might be trying too hard with the brace expansion...

    – mikeserv
    Dec 29 '14 at 0:39











  • The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

    – MERose
    Dec 29 '14 at 0:43











  • Please explain in detail (i.e. with example values) what you want to happen.

    – Hauke Laging
    Dec 29 '14 at 0:56
















4















I would like to generate a number of arrays that differ only by year. In the loop, I create the arrays with brace expansion and a variable.



I tried the following code without success:



LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
declare -a 'y$year=('"$LIST"'-$year)'
echo "${y$year[@]}"
done


The outcome should be the list of the following entries:



y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
...
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


I don't need to print them, just use them in a loop as well as pass them as arguments. Because of the second, eval in the loop is not sufficient.










share|improve this question

























  • Why the hardquotes there? I think you might be trying too hard with the brace expansion...

    – mikeserv
    Dec 29 '14 at 0:39











  • The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

    – MERose
    Dec 29 '14 at 0:43











  • Please explain in detail (i.e. with example values) what you want to happen.

    – Hauke Laging
    Dec 29 '14 at 0:56














4












4








4


1






I would like to generate a number of arrays that differ only by year. In the loop, I create the arrays with brace expansion and a variable.



I tried the following code without success:



LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
declare -a 'y$year=('"$LIST"'-$year)'
echo "${y$year[@]}"
done


The outcome should be the list of the following entries:



y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
...
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


I don't need to print them, just use them in a loop as well as pass them as arguments. Because of the second, eval in the loop is not sufficient.










share|improve this question
















I would like to generate a number of arrays that differ only by year. In the loop, I create the arrays with brace expansion and a variable.



I tried the following code without success:



LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
declare -a 'y$year=('"$LIST"'-$year)'
echo "${y$year[@]}"
done


The outcome should be the list of the following entries:



y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
...
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


I don't need to print them, just use them in a loop as well as pass them as arguments. Because of the second, eval in the loop is not sufficient.







shell-script array brace-expansion






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 29 '14 at 1:13







MERose

















asked Dec 29 '14 at 0:35









MERoseMERose

299418




299418













  • Why the hardquotes there? I think you might be trying too hard with the brace expansion...

    – mikeserv
    Dec 29 '14 at 0:39











  • The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

    – MERose
    Dec 29 '14 at 0:43











  • Please explain in detail (i.e. with example values) what you want to happen.

    – Hauke Laging
    Dec 29 '14 at 0:56



















  • Why the hardquotes there? I think you might be trying too hard with the brace expansion...

    – mikeserv
    Dec 29 '14 at 0:39











  • The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

    – MERose
    Dec 29 '14 at 0:43











  • Please explain in detail (i.e. with example values) what you want to happen.

    – Hauke Laging
    Dec 29 '14 at 0:56

















Why the hardquotes there? I think you might be trying too hard with the brace expansion...

– mikeserv
Dec 29 '14 at 0:39





Why the hardquotes there? I think you might be trying too hard with the brace expansion...

– mikeserv
Dec 29 '14 at 0:39













The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

– MERose
Dec 29 '14 at 0:43





The hardquotes, because I want to use the array in a loop while passing the entries as arguments.

– MERose
Dec 29 '14 at 0:43













Please explain in detail (i.e. with example values) what you want to happen.

– Hauke Laging
Dec 29 '14 at 0:56





Please explain in detail (i.e. with example values) what you want to happen.

– Hauke Laging
Dec 29 '14 at 0:56










3 Answers
3






active

oldest

votes


















6














Deferring brace expansion is really a case for eval, particularly if you want to stringify things — ordinary parameter expansion doesn't do the right thing at the right time.



This should do what it seems you wanted:



LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
eval "y$year=($LIST-$year)"
tmp="y$year[@]"
echo "${!tmp}"
done


You can't indirect into an array, so it's necessary to stringify the array inside an eval too if you want to print it out. If you don't, you can take out everything after the ;. tmp is used for indirect expansion: with tmp set to "y$year[@]", where $year is replaced with its value, the expansion ${!tmp} gives the contents of this iteration's array (what ${y1998[@]}, etc, would have expanded to).



The above will output:



JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


and also create arrays y1998...y2011. The declares aren't strictly necessary, although they do let you skip an eval if you're aiming for that and don't need to stringify.



I suggest that this probably isn't the way you really want to achieve your underlying goal, though, whatever that is. Nested loops aren't evil, and if any bit of it's hardcoded you can abstract that out.






share|improve this answer


























  • why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

    – mikeserv
    Dec 29 '14 at 1:16













  • Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

    – Michael Homer
    Dec 29 '14 at 1:19













  • Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

    – MERose
    Dec 29 '14 at 1:28











  • If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

    – Michael Homer
    Dec 29 '14 at 1:30






  • 1





    I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

    – Michael Homer
    Dec 29 '14 at 2:18



















4














Here's one way (with brace expansion):



unset y _y
for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
do case "${_y=y${y#*-}[@]}" in
(y${y#-}*) echo "${!_y}" ;;
(*) declare -a "${_y%???}+=($y)";;
esac; unset y _y; done


That will expand your parameter set for the for loop out to all of your desired values plus an extra last set which will consist only of the years. For each that does not begin with a digit declare adds an array member to whatever y${y##*[!0-9]} comes to, and for each that does, echo prints it.



So for the first 36 iterations it builds each array, and for the last 6 it prints each. The output is:



JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


Here is an alternative, perhaps...



for year in 1998 1999 2000 2009 2010 2011
do printf "%s-$year " JF JFE RFS JBF JFI JMCB
echo; done


That would at least get you the same output...
To also store that in an array as well, probably you could...



for year in 1998 1999 2000 2009 2010 2011
do declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
tee /dev/fd/2 ))"
year=y$year[@]; year=(${!year})
echo "${#year[@]}"
done 2>&1; unset year


This is the output from the second command, but the first prints the same sans the 6 - which just indicates the array member count.



JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6


Remember that declare is a command and the var$expand=(something $expand) argument is just that - an arg. declare's args are expanded in the same way as any other - which is not true of a var$expand=$expand statement. So you can indirectly declare in the same way you can indirectly export or whatever - the hardquotes you use are not necessary I think.






share|improve this answer

































    2














    Convert the brace expansion to an array via set --.



    Then you have a simple two dimensional loop to construct your output:



    set -- {JF,JFE,RFS,JBF,JFI,JMCB}
    for year in {1998..2000} {2009..2011}; do
    printf "y%s: " $year
    for code do
    printf "%s-%s " $code $year
    done
    echo
    done


    Yields:



    y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
    y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
    y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
    y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
    y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
    y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011





    share|improve this answer

























      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%2f176350%2fcreate-arrays-with-brace-expansion-in-loop%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      6














      Deferring brace expansion is really a case for eval, particularly if you want to stringify things — ordinary parameter expansion doesn't do the right thing at the right time.



      This should do what it seems you wanted:



      LIST={JF,JFE,RFS,JBF,JFI,JMCB}
      for year in {1998..2000} {2009..2011}
      do
      eval "y$year=($LIST-$year)"
      tmp="y$year[@]"
      echo "${!tmp}"
      done


      You can't indirect into an array, so it's necessary to stringify the array inside an eval too if you want to print it out. If you don't, you can take out everything after the ;. tmp is used for indirect expansion: with tmp set to "y$year[@]", where $year is replaced with its value, the expansion ${!tmp} gives the contents of this iteration's array (what ${y1998[@]}, etc, would have expanded to).



      The above will output:



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


      and also create arrays y1998...y2011. The declares aren't strictly necessary, although they do let you skip an eval if you're aiming for that and don't need to stringify.



      I suggest that this probably isn't the way you really want to achieve your underlying goal, though, whatever that is. Nested loops aren't evil, and if any bit of it's hardcoded you can abstract that out.






      share|improve this answer


























      • why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

        – mikeserv
        Dec 29 '14 at 1:16













      • Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

        – Michael Homer
        Dec 29 '14 at 1:19













      • Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

        – MERose
        Dec 29 '14 at 1:28











      • If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

        – Michael Homer
        Dec 29 '14 at 1:30






      • 1





        I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

        – Michael Homer
        Dec 29 '14 at 2:18
















      6














      Deferring brace expansion is really a case for eval, particularly if you want to stringify things — ordinary parameter expansion doesn't do the right thing at the right time.



      This should do what it seems you wanted:



      LIST={JF,JFE,RFS,JBF,JFI,JMCB}
      for year in {1998..2000} {2009..2011}
      do
      eval "y$year=($LIST-$year)"
      tmp="y$year[@]"
      echo "${!tmp}"
      done


      You can't indirect into an array, so it's necessary to stringify the array inside an eval too if you want to print it out. If you don't, you can take out everything after the ;. tmp is used for indirect expansion: with tmp set to "y$year[@]", where $year is replaced with its value, the expansion ${!tmp} gives the contents of this iteration's array (what ${y1998[@]}, etc, would have expanded to).



      The above will output:



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


      and also create arrays y1998...y2011. The declares aren't strictly necessary, although they do let you skip an eval if you're aiming for that and don't need to stringify.



      I suggest that this probably isn't the way you really want to achieve your underlying goal, though, whatever that is. Nested loops aren't evil, and if any bit of it's hardcoded you can abstract that out.






      share|improve this answer


























      • why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

        – mikeserv
        Dec 29 '14 at 1:16













      • Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

        – Michael Homer
        Dec 29 '14 at 1:19













      • Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

        – MERose
        Dec 29 '14 at 1:28











      • If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

        – Michael Homer
        Dec 29 '14 at 1:30






      • 1





        I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

        – Michael Homer
        Dec 29 '14 at 2:18














      6












      6








      6







      Deferring brace expansion is really a case for eval, particularly if you want to stringify things — ordinary parameter expansion doesn't do the right thing at the right time.



      This should do what it seems you wanted:



      LIST={JF,JFE,RFS,JBF,JFI,JMCB}
      for year in {1998..2000} {2009..2011}
      do
      eval "y$year=($LIST-$year)"
      tmp="y$year[@]"
      echo "${!tmp}"
      done


      You can't indirect into an array, so it's necessary to stringify the array inside an eval too if you want to print it out. If you don't, you can take out everything after the ;. tmp is used for indirect expansion: with tmp set to "y$year[@]", where $year is replaced with its value, the expansion ${!tmp} gives the contents of this iteration's array (what ${y1998[@]}, etc, would have expanded to).



      The above will output:



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


      and also create arrays y1998...y2011. The declares aren't strictly necessary, although they do let you skip an eval if you're aiming for that and don't need to stringify.



      I suggest that this probably isn't the way you really want to achieve your underlying goal, though, whatever that is. Nested loops aren't evil, and if any bit of it's hardcoded you can abstract that out.






      share|improve this answer















      Deferring brace expansion is really a case for eval, particularly if you want to stringify things — ordinary parameter expansion doesn't do the right thing at the right time.



      This should do what it seems you wanted:



      LIST={JF,JFE,RFS,JBF,JFI,JMCB}
      for year in {1998..2000} {2009..2011}
      do
      eval "y$year=($LIST-$year)"
      tmp="y$year[@]"
      echo "${!tmp}"
      done


      You can't indirect into an array, so it's necessary to stringify the array inside an eval too if you want to print it out. If you don't, you can take out everything after the ;. tmp is used for indirect expansion: with tmp set to "y$year[@]", where $year is replaced with its value, the expansion ${!tmp} gives the contents of this iteration's array (what ${y1998[@]}, etc, would have expanded to).



      The above will output:



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


      and also create arrays y1998...y2011. The declares aren't strictly necessary, although they do let you skip an eval if you're aiming for that and don't need to stringify.



      I suggest that this probably isn't the way you really want to achieve your underlying goal, though, whatever that is. Nested loops aren't evil, and if any bit of it's hardcoded you can abstract that out.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 29 '14 at 2:16

























      answered Dec 29 '14 at 1:10









      Michael HomerMichael Homer

      46.6k8122161




      46.6k8122161













      • why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

        – mikeserv
        Dec 29 '14 at 1:16













      • Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

        – Michael Homer
        Dec 29 '14 at 1:19













      • Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

        – MERose
        Dec 29 '14 at 1:28











      • If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

        – Michael Homer
        Dec 29 '14 at 1:30






      • 1





        I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

        – Michael Homer
        Dec 29 '14 at 2:18



















      • why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

        – mikeserv
        Dec 29 '14 at 1:16













      • Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

        – Michael Homer
        Dec 29 '14 at 1:19













      • Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

        – MERose
        Dec 29 '14 at 1:28











      • If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

        – Michael Homer
        Dec 29 '14 at 1:30






      • 1





        I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

        – Michael Homer
        Dec 29 '14 at 2:18

















      why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

      – mikeserv
      Dec 29 '14 at 1:16







      why do you not just eval "y$year=...; echo "${y$year[@]}""? As written your command is susceptible to all kinds of unintended effects depending on the values of $IFS and filename expansion.

      – mikeserv
      Dec 29 '14 at 1:16















      Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

      – Michael Homer
      Dec 29 '14 at 1:19







      Minimising escaped characters. All of it is definitely not something you should generally want to do for those reasons and others, yes. If you have an odd enough IFS value you're on your own.

      – Michael Homer
      Dec 29 '14 at 1:19















      Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

      – MERose
      Dec 29 '14 at 1:28





      Yes, my intention is maybe not healthy, but everything works in my little script. What do you mean by $IFS?

      – MERose
      Dec 29 '14 at 1:28













      If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

      – Michael Homer
      Dec 29 '14 at 1:30





      If you have, say, - in IFS (the input field separator) everything gets cut up in the wrong place. The same happens if you have the default IFS and a space in one of your words.

      – Michael Homer
      Dec 29 '14 at 1:30




      1




      1





      I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

      – Michael Homer
      Dec 29 '14 at 2:18





      I meant, originally, that ${!foo[@]} didn't give the values of the array named in foo in the way that indirection to a scalar does, and I discovered that foo='bar[@]' means that ${!foo} does what I wanted.

      – Michael Homer
      Dec 29 '14 at 2:18













      4














      Here's one way (with brace expansion):



      unset y _y
      for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
      do case "${_y=y${y#*-}[@]}" in
      (y${y#-}*) echo "${!_y}" ;;
      (*) declare -a "${_y%???}+=($y)";;
      esac; unset y _y; done


      That will expand your parameter set for the for loop out to all of your desired values plus an extra last set which will consist only of the years. For each that does not begin with a digit declare adds an array member to whatever y${y##*[!0-9]} comes to, and for each that does, echo prints it.



      So for the first 36 iterations it builds each array, and for the last 6 it prints each. The output is:



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


      Here is an alternative, perhaps...



      for year in 1998 1999 2000 2009 2010 2011
      do printf "%s-$year " JF JFE RFS JBF JFI JMCB
      echo; done


      That would at least get you the same output...
      To also store that in an array as well, probably you could...



      for year in 1998 1999 2000 2009 2010 2011
      do declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
      tee /dev/fd/2 ))"
      year=y$year[@]; year=(${!year})
      echo "${#year[@]}"
      done 2>&1; unset year


      This is the output from the second command, but the first prints the same sans the 6 - which just indicates the array member count.



      JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
      JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
      JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
      JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
      JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
      JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6


      Remember that declare is a command and the var$expand=(something $expand) argument is just that - an arg. declare's args are expanded in the same way as any other - which is not true of a var$expand=$expand statement. So you can indirectly declare in the same way you can indirectly export or whatever - the hardquotes you use are not necessary I think.






      share|improve this answer






























        4














        Here's one way (with brace expansion):



        unset y _y
        for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
        do case "${_y=y${y#*-}[@]}" in
        (y${y#-}*) echo "${!_y}" ;;
        (*) declare -a "${_y%???}+=($y)";;
        esac; unset y _y; done


        That will expand your parameter set for the for loop out to all of your desired values plus an extra last set which will consist only of the years. For each that does not begin with a digit declare adds an array member to whatever y${y##*[!0-9]} comes to, and for each that does, echo prints it.



        So for the first 36 iterations it builds each array, and for the last 6 it prints each. The output is:



        JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
        JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
        JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
        JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
        JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
        JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


        Here is an alternative, perhaps...



        for year in 1998 1999 2000 2009 2010 2011
        do printf "%s-$year " JF JFE RFS JBF JFI JMCB
        echo; done


        That would at least get you the same output...
        To also store that in an array as well, probably you could...



        for year in 1998 1999 2000 2009 2010 2011
        do declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
        tee /dev/fd/2 ))"
        year=y$year[@]; year=(${!year})
        echo "${#year[@]}"
        done 2>&1; unset year


        This is the output from the second command, but the first prints the same sans the 6 - which just indicates the array member count.



        JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
        JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
        JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
        JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
        JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
        JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6


        Remember that declare is a command and the var$expand=(something $expand) argument is just that - an arg. declare's args are expanded in the same way as any other - which is not true of a var$expand=$expand statement. So you can indirectly declare in the same way you can indirectly export or whatever - the hardquotes you use are not necessary I think.






        share|improve this answer




























          4












          4








          4







          Here's one way (with brace expansion):



          unset y _y
          for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
          do case "${_y=y${y#*-}[@]}" in
          (y${y#-}*) echo "${!_y}" ;;
          (*) declare -a "${_y%???}+=($y)";;
          esac; unset y _y; done


          That will expand your parameter set for the for loop out to all of your desired values plus an extra last set which will consist only of the years. For each that does not begin with a digit declare adds an array member to whatever y${y##*[!0-9]} comes to, and for each that does, echo prints it.



          So for the first 36 iterations it builds each array, and for the last 6 it prints each. The output is:



          JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
          JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
          JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
          JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
          JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
          JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


          Here is an alternative, perhaps...



          for year in 1998 1999 2000 2009 2010 2011
          do printf "%s-$year " JF JFE RFS JBF JFI JMCB
          echo; done


          That would at least get you the same output...
          To also store that in an array as well, probably you could...



          for year in 1998 1999 2000 2009 2010 2011
          do declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
          tee /dev/fd/2 ))"
          year=y$year[@]; year=(${!year})
          echo "${#year[@]}"
          done 2>&1; unset year


          This is the output from the second command, but the first prints the same sans the 6 - which just indicates the array member count.



          JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
          JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
          JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
          JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
          JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
          JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6


          Remember that declare is a command and the var$expand=(something $expand) argument is just that - an arg. declare's args are expanded in the same way as any other - which is not true of a var$expand=$expand statement. So you can indirectly declare in the same way you can indirectly export or whatever - the hardquotes you use are not necessary I think.






          share|improve this answer















          Here's one way (with brace expansion):



          unset y _y
          for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
          do case "${_y=y${y#*-}[@]}" in
          (y${y#-}*) echo "${!_y}" ;;
          (*) declare -a "${_y%???}+=($y)";;
          esac; unset y _y; done


          That will expand your parameter set for the for loop out to all of your desired values plus an extra last set which will consist only of the years. For each that does not begin with a digit declare adds an array member to whatever y${y##*[!0-9]} comes to, and for each that does, echo prints it.



          So for the first 36 iterations it builds each array, and for the last 6 it prints each. The output is:



          JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
          JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
          JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
          JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
          JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
          JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011


          Here is an alternative, perhaps...



          for year in 1998 1999 2000 2009 2010 2011
          do printf "%s-$year " JF JFE RFS JBF JFI JMCB
          echo; done


          That would at least get you the same output...
          To also store that in an array as well, probably you could...



          for year in 1998 1999 2000 2009 2010 2011
          do declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
          tee /dev/fd/2 ))"
          year=y$year[@]; year=(${!year})
          echo "${#year[@]}"
          done 2>&1; unset year


          This is the output from the second command, but the first prints the same sans the 6 - which just indicates the array member count.



          JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
          JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
          JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
          JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
          JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
          JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6


          Remember that declare is a command and the var$expand=(something $expand) argument is just that - an arg. declare's args are expanded in the same way as any other - which is not true of a var$expand=$expand statement. So you can indirectly declare in the same way you can indirectly export or whatever - the hardquotes you use are not necessary I think.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 29 '14 at 4:52

























          answered Dec 29 '14 at 1:01









          mikeservmikeserv

          45.5k668154




          45.5k668154























              2














              Convert the brace expansion to an array via set --.



              Then you have a simple two dimensional loop to construct your output:



              set -- {JF,JFE,RFS,JBF,JFI,JMCB}
              for year in {1998..2000} {2009..2011}; do
              printf "y%s: " $year
              for code do
              printf "%s-%s " $code $year
              done
              echo
              done


              Yields:



              y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
              y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
              y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
              y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
              y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
              y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011





              share|improve this answer






























                2














                Convert the brace expansion to an array via set --.



                Then you have a simple two dimensional loop to construct your output:



                set -- {JF,JFE,RFS,JBF,JFI,JMCB}
                for year in {1998..2000} {2009..2011}; do
                printf "y%s: " $year
                for code do
                printf "%s-%s " $code $year
                done
                echo
                done


                Yields:



                y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
                y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
                y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
                y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
                y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
                y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011





                share|improve this answer




























                  2












                  2








                  2







                  Convert the brace expansion to an array via set --.



                  Then you have a simple two dimensional loop to construct your output:



                  set -- {JF,JFE,RFS,JBF,JFI,JMCB}
                  for year in {1998..2000} {2009..2011}; do
                  printf "y%s: " $year
                  for code do
                  printf "%s-%s " $code $year
                  done
                  echo
                  done


                  Yields:



                  y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
                  y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
                  y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
                  y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
                  y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
                  y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011





                  share|improve this answer















                  Convert the brace expansion to an array via set --.



                  Then you have a simple two dimensional loop to construct your output:



                  set -- {JF,JFE,RFS,JBF,JFI,JMCB}
                  for year in {1998..2000} {2009..2011}; do
                  printf "y%s: " $year
                  for code do
                  printf "%s-%s " $code $year
                  done
                  echo
                  done


                  Yields:



                  y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
                  y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
                  y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
                  y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
                  y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
                  y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 2 hours ago









                  mikeserv

                  45.5k668154




                  45.5k668154










                  answered Apr 21 '17 at 13:33









                  bishopbishop

                  2,0762822




                  2,0762822






























                      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%2f176350%2fcreate-arrays-with-brace-expansion-in-loop%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

                      サソリ

                      広島県道265号伴広島線

                      Setup Asymptote in Texstudio