Bash split string
Solution 1
It looks like the separator between the fields is an space. Hence, you can use cut
to split them:
file=$(echo "${MY_ARR[1]}" | cut -d' ' -f1)
parameter=$(echo "${MY_ARR[1]}" | cut -d' ' -f2-)
-f1
means the first parameter.-f2-
means everything from the second parameter.
Solution 2
You can use read
:
$ read file parameter <<< ${MY_ARR[1]}
$ echo "$file"
./path/path2/name.exe
$ echo "$parameter"
'word1 word2' 'name3,name4,name5'
Solution 3
Given this array:
MY_ARR[0]="./path/path2/name.exe 'word1 word2' 'name1,name2'"
MY_ARR[1]="./path/path2/name.exe 'word1 word2' 'name3,name4,name5'"
MY_ARR[2]=".name.exe 'word1 word2'"
MY_ARR[3]="name.exe"
MY_ARR[4]="./path/path2/name.exe 'word1 word2' 'name1'"
MY_ARR[5]="./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe'"
Lets make 2 new arrays MY_FILES and MY_PARAMETERS
for MY_ARR_INDEX in ${!MY_ARR[*]} ; do
######
# Set the current file in new array.
MY_FILES[ ${MY_ARR_INDEX} ]=${MY_ARR[ ${MY_ARR_INDEX} ]// *}
######
# Set the current parameters in new array
MY_PARAMETERS[ ${MY_ARR_INDEX} ]=${MY_ARR[ ${MY_ARR_INDEX} ]#* }
######
# Show the user whats happening
# (from here until done is just printing info.)
printf "MY_FILES[ ${MY_ARR_INDEX} ]=\"%s\" ; MY_PARAMETERS[ ${MY_ARR_INDEX} ]=\"%s\"\n" \
\
"${MY_ARR[ ${MY_ARR_INDEX} ]// *}" "${MY_ARR[ ${MY_ARR_INDEX} ]#* }"
done
MY_FILES[ 0 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 0 ]="'word1 word2' 'name1,name2'"
MY_FILES[ 1 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 1 ]="'word1 word2' 'name3,name4,name5'"
MY_FILES[ 2 ]=".name.exe" ; MY_PARAMETERS[ 2 ]=" 'word1 word2'"
MY_FILES[ 3 ]="name.exe" ; MY_PARAMETERS[ 3 ]="name.exe"
MY_FILES[ 4 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 4 ]="'word1 word2' 'name1'"
MY_FILES[ 5 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 5 ]="'word1 word2' 'name.exe, name4.exe, name5.exe'"
How to access each file:
for MY_ARR_INDEX in ${!MY_FILES[*]} ; do
CUR_FILE=${MY_FILES[ ${MY_ARR_INDEX} ] }
echo "# Do something with this file: ${CUR_FILE}"
done
Output:
Do something with this file: ./path/path2/name.exe
Do something with this file: ./path/path2/name.exe
Do something with this file: .name.exe
Do something with this file: name.exe
Do something with this file: ./path/path2/name.exe
Do something with this file: ./path/path2/name.exe
How to access each parameter :
for MY_ARR_INDEX in ${!MY_PARAMETERS[*]} ; do
CUR_FILE=${MY_FILES[ ${MY_ARR_INDEX} ]}
echo "# Do something with this parameter: ${CUR_FILE}"
done
Output:
Do something with this parameter: ./path/path2/name.exe
Do something with this parameter: ./path/path2/name.exe
Do something with this parameter: .name.exe
Do something with this parameter: name.exe
Do something with this parameter: ./path/path2/name.exe
Do something with this parameter: ./path/path2/name.exe
Since ${!MY_FILES[ [*]} results in the index NUMBERS of array MY_FILES you can also use the same index numbers to access the other arrays.In this way, you may access multiple columns of data in the same loop. Like so:
################
#
# Print each file and matching parameter(s)
#
################
# Set a printf format string so we can print all things nicely.
MY_PRINTF_FORMAT="# %25s %s\n"
################
#
# Print the column headings and use index numbers
#
# to print adjacent array elements.
#
################
(
printf "${MY_PRINTF_FORMAT}" "FILE" "PARAMETERS" "----" "----------"
for MY_ARR_INDEX in ${!MY_FILES[*]} ; do
printf "${MY_PRINTF_FORMAT}" "${MY_FILES[ ${MY_ARR_INDEX} ]}" "${MY_PARAMETERS[ ${MY_ARR_INDEX} ]}"
done
)
Output :
FILE PARAMETERS
---- ----------
./path/path2/name.exe 'word1 word2' 'name1,name2'
./path/path2/name.exe 'word1 word2' 'name3,name4,name5'
.name.exe 'word1 word2'
name.exe name.exe
./path/path2/name.exe 'word1 word2' 'name1'
./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe'
Solution 4
Unless I'm missing something, simplest and most portable way would be to just use two variations of bash expansion for this.
file="${MY_ARR[0]%%' '*}"
parameter="${MY_ARR[0]#*' '}"
Explanation
-
"${MY_ARR[0]%%' '*}"
- This removes the first space and anything after it, and returns remaining part -
"${MY_ARR[0]#*' '}"
- This removes everything up to the first space, and returns the remaining part
For a more detailed explanation, see the Parameter Expansion
section of the bash man page
idobr
Updated on February 01, 2020Comments
-
idobr over 4 years
I have the following data in array:
MY_ARR[0]="./path/path2/name.exe 'word1 word2' 'name1,name2'" MY_ARR[1]="./path/path2/name.exe 'word1 word2' 'name3,name4,name5'" MY_ARR[2]=".name.exe 'word1 word2'" MY_ARR[3]="name.exe" MY_ARR[4]="./path/path2/name.exe 'word1 word2' 'name1'" MY_ARR[5]="./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe'"
I want to divide it into two variables:
$file
and$parameter
.Example:
file="./path/path2/name.exe" parameter="'word1 word2' 'name1,name2'"
I can do it with awk:
parameter=$(echo "${MY_ARR[1]}" | awk -F\' '{print $2 $4}') file=$(echo "${MY_ARR[1]}" | awk -F\' '{print $1}')
This needs to remove trailing spaces and looks to complicated.
Is there a better way to do it?
-
idobr over 11 yearsyes, I know about cut. I used it with my first try. I refused to use it because I was afraid to miss the third and fouth fieleds if the are spaces... Need to check!
-
chepner over 10 yearsThis is the better solution, as it doesn't require multiple new processes to accomplish the task (one for the command substitution, two for either side of the pipeline).