0

Let's say I have this string:

NAMES="Mike&George&Norma"
IFS=$'&'
for NAME in $NAMES
do
  echo ${NAME}
done

So I can loop through the NAMES.

But what if I only need George, i.e. the name at index 1?

How can I get NAMES[1]?

LongHike
  • 4,016
  • 4
  • 37
  • 76

3 Answers3

2

If mapfile aka readarray is available/acceptable.

#!/usr/bin/env bash

names="Mike&George&Norma"

mapfile -td '&' name <<< "$names"

printf '%s\n' "${name[@]}"

Prints all elements/strings in between the &, so

printf '%s\n' "${name[0]}"
printf '%s\n' "${name[1]}"
printf '%s\n' "${name[2]}"

Should print them names one by one.

See the builtin section of the bash manual https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html

Jetchisel
  • 7,493
  • 2
  • 19
  • 18
1
$ NAMES="Mike&George&Norma"; 
$ echo "$NAMES" | cut -d'&' -f2

 George

field counting starts with 1, unlike array indexing.

karakfa
  • 66,216
  • 7
  • 41
  • 56
1

Using OP's current code one idea would be to add a counter to the loop processing, eg:

NAMES="Mike&George&Norma"

loop_ctr=-1
match_ctr=1

origIFS="${IFS}"                 # save current IFS
IFS=$'&'

for NAME in $NAMES
do
    ((loop_ctr++))
    [[ "${loop_ctr}" -ne "${match_ctr}" ]] &&    # if loop_ctr != match_ctr then skip to next pass through loop
    continue

    echo ${NAME}
done

IFS="${origIFS}"                 # reset to original IFS

This generates as output:

George

NOTE: My preference would be to parse the string into an array (via mapfile/readarray) ... and @jetchisel beat me to that idea :-)

markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • I would have deleted my `mapfile` answer if you did not deleted yours. – Jetchisel Apr 11 '21 at 14:38
  • 1
    I was in the process of additional editing that basically repeated what you had just posted so ... twas easier to just delete that (incomplete) chunk of my answer; no biggie ... it's not like we can cash in our SO points for anything useful :-) – markp-fuso Apr 11 '21 at 14:40