[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: bash scripting question

Neal Lippman <nl@lippman.org> [2002-11-02 22:51:00 -0500]:
> I am trying to solve a bash scripting problem, but I cannot figure it
> out.
> I frequently need to execute a command of the form:
> 	for x in {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z); 	do
> 		<do something with each x> ;
> 	done
> This works fine if I actually type out the entire alphabet list on the
> command line as above, but that's sort of a pain.

Yes, that could be.  Are you refering to literal letters?  Or is that
just an example of a bigger word?

> So, I tried setting a
> shell variable to the alphabet string (export alpha="A,B,C,...,Z"), but
> then the command:
> 	for x in {$alpha} ; 
> 	do
> 		echo $x;
> 	done
> winds up printing the string "{A,B,C,...,Z}" rather than each letter on
> a separate line as expected.

A simple syntax error which you have probably already deduced.  Change
that one line to this.

	for x in ${alpha} ; 

And in actuality the curly braces are not needed here and in your case
are just getting in the way.  I would not include them in this
particular case.  I only include them when they are needed to split a
string of characters into different variables.

	for x in $alpha ;

Also, you need to use spaces instead of commas to seperate your
items.  (Or as another poster almost suggested, set IFS to include the
comma but that would make this script more confusing and I recommend
doing it this way instead.)

  alpha="A B C D E"
  for x in $alpha ; do
    echo $x

> I've tried various versions, including escaping the {} characters, etc,
> using xargs, etc, but I cannot hit upon a sequence that works.
> I also tried writing a program that printed the alphabet string to
> stdout, but same results.

You don't really need a variable.  Just run the for-loop.

  for x in A B C D E F G H I J K L M N O P Q R S T U V X Y Z ; do
    echo $x


P.S.  Perl has an operator which might help here.  A snippet from the
perl docs.  Perhaps this might be helpful to take the drudgery out of
walking through a list of letters.  But I will leave implementation as
an exercise to the reader since it starts to look like line noise at
that point.  The above is really simpler to grasp in an instant what
is happening.

       The auto-increment operator has a little extra builtin
       magic to it.  If you increment a variable that is numeric,
       or that has ever been used in a numeric context, you get a
       normal increment.  If, however, the variable has been used
       in only string contexts since it was set, and has a value
       that is not the empty string and matches the pattern
       "/^[a-zA-Z]*[0-9]*\z/", the increment is done as a string,
       preserving each character within its range, with carry:

           print ++($foo = '99');      # prints '100'
           print ++($foo = 'a0');      # prints 'a1'
           print ++($foo = 'Az');      # prints 'Ba'
           print ++($foo = 'zz');      # prints 'aaa'

       The auto-decrement operator is not magical.

Quick example of use:

  perl -le "print ++(\$foo = 'A')"

Attachment: pgpQJDunLEpTx.pgp
Description: PGP signature

Reply to: