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.
-
2Efforts at achieving terseness here are going to be doing so at the expense of correctness -- not generally a worthwhile tradeoff.Charles Duffy– Charles Duffy2018-12-03 23:35:29 +00:00Commented Dec 3, 2018 at 23:35
2 Answers
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.
2 Comments
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.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
>