0

I have an array say a=(one two three split_array four five). I need to find split_array based on a know substring split and finally get all the items before it i.e one two three. Is there any way to achieve this by using parameter substitution. I can do it using loop but looking for smarter way to achieve this.

1
  • 2
    Efforts at achieving terseness here are going to be doing so at the expense of correctness -- not generally a worthwhile tradeoff. Commented Dec 3, 2018 at 23:35

2 Answers 2

1

I'm not sure if this is smart but you can once concatenate the array into a string and perform the parameter substitution on it:

declare -a a=(one two three split_array four five)
b="${a[*]}"
declare -a c=( ${b%% split_array*} )
for i in ${c[@]}; do
    echo "$i"
done

the output:

one
two
three
  • b="${a[*]}" merges the elements of the array to a space-delimited string
  • ${b%% split_array*} removes the pattern " split_array*" of $b

Note that the script above is based on the assumption that the elements of the array do not contain IFS characters.

For such a case you can modify the IFS to a character which may not be used in the elements of the array, e.g. the escape character:

ESC=$'\e'       # the escape character
declare -a a=("one word" two three split_array four five)
ifs_bak=$IFS    # back up IFS
IFS=$ESC        # new delimiter
b="${a[*]}"
declare -a c=( ${b%%${ESC}split_array*} )
for ((i=0; i<${#c[@]}; i++)); do
    echo "${c[$i]}"     # test output
done
IFS=$ifs_bak    # retrieve IFS

the output:

one word
two
three

It may not be still 100% guaranteed that the escape character is never used in the array elements. There is always a risk when we merge an array into a string.

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

This will split a=("one word" two three split_array four ) to have one and word as two separate entries; and a=( "*" split_array ) will have the * replaced with a list of files. Much less buggy if you do the split inside the for loop.
You're right. I should have mentioned I have assumed each element of the array does not contain whitespaces/tabs. Otherwise the script above will not be reusable.
1

If you are considering Perl, check this

>  perl -e '@a=qw(one two three split_array four five);for(@a) { last if /split/; print "$_\n" }'
one
two
three
>

If exporting as a variable,

> export a="one two three split_array four five"
> perl -e ' @a=split / /, $ENV{a}; for(@a) { last if /split/; print "$_\n" }'
one
two
three
>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.