简体   繁体   中英

How to loop through the first n letters of the alphabet in bash

I know that to loop through the alphabet, one can do

for c in {a..z};  do   something;  done

My question is, how can I loop through the first n letters (eg to build a string) where n is a variable/parameter given in the command line.

I searched SO, and only found answers doing this for numbers, eg using C-style for loop or seq (see eg How do I iterate over a range of numbers defined by variables in Bash? ). And I don't have seq in my environment.

Thanks.

The straightforward way is sticking them in an array and looping over that by index:

#!/bin/bash
chars=( {a..z} )
n=3
for ((i=0; i<n; i++))
do
  echo "${chars[i]}"
done

Alternatively, if you just want them dash-separated:

printf "%s-" "${chars[@]:0:n}"

that other guy's answer is probably the way to go , but here's an alternative that doesn't require an array variable :

n=3 # sample value

i=0 # var. for counting iterations
for c in {a..z};  do 
  echo $c # do something with "$c"
  (( ++i == n )) && break # exit loop, once desired count has been reached
done

@rici points out in a comment that you could make do without aux. variable $i by using the conditional (( n-- )) || break (( n-- )) || break to exit the loop, but note that this modifies $n .


Here's another array-free, but less efficient approach that uses substring extraction (parameter expansion) :

n=3 # sample value

# Create a space-separated list of letters a-z.
# Note that chars={a..z} does NOT work.
chars=$(echo {a..z})

# Extract the substring containing the specified number
# of letters using parameter expansion with an arithmetic expression,
# and loop over them.
# Note:
#  - The variable reference must be _unquoted_ for this to work.
#  - Since the list is space-separated, each entry spans 2 
#    chars., hence `2*n` (you could subtract 1 after, but it'll work either way).
for c in ${chars:0:2*n};  do 
  echo $c # do something with "$c"
done

Finally, you can combine the array and list approaches for concision, although the pure array approach is more efficient:

n=3 # sample value

chars=( {a..z} ) # create array of letters

# `${chars[@]:0:n}` returns the first n array elements as a space-separated list
# Again, the variable reference must be _unquoted_.
for c in ${chars[@]:0:n}; do
  echo $c # do something with "$c"
done

Are you only iterating over the alphabet to create a subset? If that's the case, just make it simple:

 $ alpha=abcdefghijklmnopqrstuvqxyz
 $ n=4
 $ echo ${alpha:0:$n}
 abcd

Edit . Based on your comment below, do you have sed ?

% sed -e 's/./&-/g' <<< ${alpha:0:$n}
a-b-c-d-

You can loop through the character code of the letters of the alphabet and convert back and forth:

# suppose $INPUT is your input
INPUT='x'
# get the character code and increment it by one
INPUT_CHARCODE=`printf %x "'$INPUT"`
let INPUT_CHARCODE++

# start from character code 61 = 'a'
I=61  
while [ $I -ne $INPUT_CHARCODE ]; do
    # convert the index to a letter
    CURRENT_CHAR=`printf "\x$I"`
    echo "current character is: $CURRENT_CHAR"
    let I++
done

This question and the answers helped me with my problem, partially.
I needed to loupe over a part of the alphabet based on a letter in bash.

Although the expansion is strictly textual

I found a solution: and made it even more simple:

START=A
STOP=D
for letter in $(eval echo {$START..$STOP}); do
    echo $letter
done

Which results in:

A
B
C
D

Hope it's helpful for someone looking for the same problem i had to solve, and ends up here as well

( also answered here )

And the complete answer to the original question is:

START=A
n=4

OFFSET=$( expr $(printf "%x" \'$START) + $n)
STOP=$(printf "\x$OFFSET") 

for letter in $(eval echo {$START..$STOP}); do
    echo $letter
done

Which results in the same:

A
B
C
D

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM