Reputation: 137
I'd like to create array containing
Speed: 10500 Mbps
Size: 122400 MB
Load: 4544 Kg
Distance: 232680 miles
Acceleration: 11200 meters/s2
Deviation: 1100 Wierdos
From the following code:
read -r -d '' TEST_STRING << EOM
Speed: 10500 Mbps; Size: 122400 MB
Load: 4544 Kg; Distance: 232680 miles
Acceleration: 11200 meters/s2; Deviation: 1100 Wierdos
EOM
STRINGS_ARRAY=()
RE_INTRALINEDELIMITER=";"
while IFS=$'\n' read -a LINE; do
if [[ $LINE =~ $RE_INTRALINEDELIMITER ]]; then
echo "(intraline): $LINE"
while IFS=$';' read -a SUBSTR; do
echo "(substr): $SUBSTR"
done <<< "$LINE"
fi
done <<< "$TEST_STRING"
(echoes are added for debugging and as an empty operator). Then process lines with some functions and finally to assembly it back to the original string.
But for SUBSTR
I get only first sub-string from every string (before semicolon). What I'm doing wrong?
Upvotes: 2
Views: 855
Reputation: 530920
Use read
twice; once get a line, and again to split that line.
test_string='Speed: 10500 Mbps; Size: 122400 MB
Load: 4544 Kg; Distance: 232680 miles
Acceleration: 11200 meters/s2; Deviation: 1100 Wierdos'
while IFS= read -r line; do
IFS=";" read -r fields <<< "$line"
strings_array+=("${fields[@]}")
done <<< "$test_string"
Upvotes: 0
Reputation: 85530
With read -ra
you are basically reading into an array SUBSTR
but only trying to print it in a string variable's context. Try printing the whole array, which should have the complete line stored.
echo "(substr): ${SUBSTR[@]}"
Also mind the -a
usage earlier in the code for LINE
where you have the entire line stored as an array.
Also if you have pretty recent versions of bash
installed, try using mapfile
/readarray
to parse multi-line output into an array. Your entire requirement could very well be reduced to
re_delimiter=';'
mapfile -t stringArray <<<"$TEST_STRING"
This stores the entire string in the array, from which you loop over one entry at a time to see if the line has a ;
character present. I have initialized wholeArray
here to store all the ;
delimited strings from all the lines in your input string.
wholeArray=()
for line in "${stringArray[@]}"; do
substringArray=()
if [[ $line =~ $re_delimiter ]]; then
IFS=';' read -ra substringArray <<<"$line"
wholeArray+=( "${substringArray[@]}" )
fi
done
and now print the entire array content as
declare -p wholeArray
declare -a wholeArray='([0]="Speed: 10500 Mbps" [1]=" Size: 122400 MB" [2]="Load: 4544 Kg" [3]=" Distance: 232680 miles" [4]="Acceleration: 11200 meters/s2" [5]=" Deviation: 1100 Wierdos")'
(or) print the element one at a time using a proper for-loop
for entry in "${wholeArray[@]}"; do
printf '%s\n' "$entry"
done
Also always use upper-case variables to store variable names to not confuse with environment variables maintained by the shell.
Upvotes: 2
Reputation: 19305
Another way to split strings, using shell expansions and avoiding read which is slow :
tmp=$TEST_STRING
while [[ $tmp = *[\;$'\n']* ]]; do
item=${tmp%%[;$'\n']*} # to remove the largest suffix starting with ; or newline
tmp=${tmp#*[;$'\n']} # to remove the shortest prefix ending with ; or new line
echo "[$item]"
done
Upvotes: 0