I am new to shell scripting. I am trying to create an array ,where the string x (as of now i am using static value for testing purpose) will be an input by the user during the run time.
#!/bin/bash
x="101:Redmi:Mobile:15000#102:Samsung:TV:20000#103:OnePlus:Mobile:35000#104:HP:Laptop:65000#105:Samsung:Mobile:10000#106:Samsung:TV:30000"
i=0
index=0
declare -a categ_array=()
declare -a amnt_array=()
declare -a cnt_array=()
echo "$x" | tr '#' '\n' | cut -d ":" -f 3-4 | while read -r line ;
do
echo "------Inside while loop------"
echo $line
category=$(echo "$line" | cut -d ":" -f 1 )
echo $category
amount=$(echo "$line" | cut -d ":" -f 2 )
echo $amount
echo $i
categ_array[$i]=${category}
amnt_array[$i]=${amount}
cnt_array[$i]=1
let i =1
done
echo Category:
for n in "${categ_array[@]}"
do
echo $n
done ```
When I run the above script, I do not get any output. Where as I want output as
``` categ_array should have data as (Mobile,TV,Mobile,Laptop,Mobile,TV) ```
```amnt_array should have data as (15000,20000,35000,65000,10000,30000)```
Can someone tell me where am I going wrong?
CodePudding user response:
The fundamental problem is that the arrays are populated inside a pipeline. Pipeline stages are run in sub-processes so changes to variables made within them are not visible in the main program. See What happens when reading into a variable in a pipeline?.
Since the arrays are populated in the last stage of the pipeline, you can fix the problem if you are running Bash version 4.2 or later by putting
shopt -s lastpipe
in the code before the pipeline. That causes the last stage of the pipeline to be run in the top-level shell so changes to variables are visible after the pipeline completes.
Since you are using Bash, you can do what you want without using pipelines (or external commands like tr
and cut
). Try this Shellcheck-clean code:
#! /bin/bash -p
x="101:Redmi:Mobile:15000#102:Samsung:TV:20000#103:OnePlus:Mobile:35000#104:HP:Laptop:65000#105:Samsung:Mobile:10000#106:Samsung:TV:30000"
declare -a categ_array=()
declare -a amnt_array=()
declare -a cnt_array=()
while IFS= read -r -d '#' line || [[ -n $line ]]; do
IFS=: read -r _ _ category amount <<<"$line"
categ_array =( "$category" )
amnt_array =( "$amount" )
cnt_array =( 1 )
done <<<"$x"
echo Category:
for n in "${categ_array[@]}"; do
echo "$n"
done