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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.