Bash script array to csv - arrays

I want to do comma separated string from my array. In my script i collecting data to array outputArr and then i want to echo it to check it out, but now i'm stuck. I want to print it on console using:
echo ${outputArr[*]}
But i'm getting wrong output. So i'm trying to debug it and write it like this:
echo ${outputArr[0]}
echo ${outputArr[1]}
echo ${outputArr[*]}
echo "-------------"
OK here is my output:
Terminally Yours
2204
2204nally Yours
-------------
and other example:
Alfa
1491
1491
-------------
Why this is overwritten with space in the beginning? Of course my goal is (finally):
Alfa;1491
In this point:
Alfa1491
EDIT:
while read -r line
do
singleLine=$line
if [[ $singleLine =~ $regexVenueName ]]
then
singleLine=${singleLine/<span id=\"ctl00_MainContent_lbPartner\" class=\"Partner\">/}
singleLine=${singleLine/<\/span> <br \/><br \/>/}
partnerVenueNameOutput+="$singleLine"
outputArr[0]=$singleLine
fi
done < "$f"

Your array contains elements with carriage returns:
$ foo=($'\rterminally yours' $'\r2204')
$ echo "${foo[0]}"
terminally yours
$ echo "${foo[1]}"
2204
$ echo "${foo[*]}"
2204inally yours
For your code, you can add the following to remove the carriage return from the variable:
singleLine=${singleLine//$'\r'/}

To remove any trailing carriage returns from each array element, try
outputArray=( "${outputArray[#]%$'\r'}" )
However, it would probably be better to examine how outputArray is set in the first place and prevent the carriage returns from being added in the first place. If you are reading from a file that uses DOS line endings, try "cleaning" it first using dos2unix.

Related

Shell - Taking the input from the user from each line

I'm trying to take the input from the user into an array but Shell is accepting user input separated by spaced. Is there any way to accept the user input given separately in each line. My code below:
#!/bin/bash
echo "enter the servers names..."
read -a array
for i in "${array[#]}"
do
echo $i
done
exit 0
Input:
hello world
I want to the input to be taken as below (in two different lines):
hello
world
Kindly help. Thanks.
You can specify the delimiter of read to stop reading, rather than newline. (read man page)
-d delim continue until the first character of DELIM is read, rather
than newline
For example:
read -d':' -a array
If you want there is no delimiter to input, you can use a loop to read into the elements of the array, then check whether the input is null string or not.
i=0
read "array[$i]"
while [ "${array[$i]}" ];
do
let "i = i+1"
read "array[$i]"
done
So the input will be
hello
world
# > there is one more empty line
According to help read:
Reads a single line from the standard input, or from file descriptor FD...
This loop would do instead:
echo "enter the servers names..."
i=0
until false; do
read server
[ -z "$server" ] && break
let i=i+1
array[$i]="$server"
done
for i in "${array[#]}"; do
echo $i
done
exit 0
The loop will exit on an empty line or EOF (ctrl-D).
Example session terminated by empty line:
#server:/tmp$ ./test.sh
enter the servers names...
se1
se2
se3
se1
se2
se3
Example session terminated by EOF on the empty line after se2:
#server:/tmp$ ./test.sh
enter the servers names...
se1
se2
se1
se2
Please note that I check for an empty string while reading the names; but it is possible to check for empty strings (or whatever else) in any loop, for example while printing them or doing other computations.
#!/bin/bash
echo "enter the servers names..."
read -a array -d '\n'
for i in "${array[#]}"
do
echo $i
done
exit 0
or
#!/bin/bash
echo "enter the servers names..."
readarray array
for i in "${array[#]}"
do
echo $i
done
exit 0

bash create for loop with an array variable

i am trying to make output of a command be read by a for loop, but in such a way that the loop variable would be an array. is that possible?
this is what I've been trying so far:
function samplevals() {
echo '"aa bb"'
echo '"cc dd"'
echo '"ee ff" "gg hh"'
}
samplevar='"aa bb"
"cc dd"
"ee ff" "gg hh"'
echo call function samplevals:
for x in `samplevals `; do echo ">$x<"; done
echo read variable samplevar:
echo $samplevar
for x in $samplevar; do echo ">$x<"; done
echo process output of 'echo samplevar:'
for x in `echo $samplevar`; do echo ">$x<"; done
echo "the thing with set"
for x in $samplevar; do set -- $x ; echo "\$1=>$1<,\$2=>$2<"; done
but the output is always the same:
>"aa<
>bb"<
>"cc<
>dd"<
>"ee<
>ff"<
>"gg<
>hh"<
Can I somehow prevent bash from splitting the elements into smaller pieces?
Along the lines of chepner's answer, using read command. The -a flag part of the command lets the output to written out to an array.
IFS=$'\t' read -ra arrayDef < <(echo -ne '"abc def"\t"ghi jkl"')
for x in "${arrayDef[#]}"; do
echo ">$x<"
done
You can replace the echo part with some command that generates such a string. Remember to update the IFS appropriately as to how the string is de-limited. In my case, I just a have the string de-limited by \t
The way to define an array in bash is
samplevars=("aa bb" "cc dd" "ee ff" "gg hh")
for x in "${samplevars[#]}"; do
echo ">$x<"
done

remove carriage return from vars in an array in bash [duplicate]

I want to do comma separated string from my array. In my script i collecting data to array outputArr and then i want to echo it to check it out, but now i'm stuck. I want to print it on console using:
echo ${outputArr[*]}
But i'm getting wrong output. So i'm trying to debug it and write it like this:
echo ${outputArr[0]}
echo ${outputArr[1]}
echo ${outputArr[*]}
echo "-------------"
OK here is my output:
Terminally Yours
2204
2204nally Yours
-------------
and other example:
Alfa
1491
1491
-------------
Why this is overwritten with space in the beginning? Of course my goal is (finally):
Alfa;1491
In this point:
Alfa1491
EDIT:
while read -r line
do
singleLine=$line
if [[ $singleLine =~ $regexVenueName ]]
then
singleLine=${singleLine/<span id=\"ctl00_MainContent_lbPartner\" class=\"Partner\">/}
singleLine=${singleLine/<\/span> <br \/><br \/>/}
partnerVenueNameOutput+="$singleLine"
outputArr[0]=$singleLine
fi
done < "$f"
Your array contains elements with carriage returns:
$ foo=($'\rterminally yours' $'\r2204')
$ echo "${foo[0]}"
terminally yours
$ echo "${foo[1]}"
2204
$ echo "${foo[*]}"
2204inally yours
For your code, you can add the following to remove the carriage return from the variable:
singleLine=${singleLine//$'\r'/}
To remove any trailing carriage returns from each array element, try
outputArray=( "${outputArray[#]%$'\r'}" )
However, it would probably be better to examine how outputArray is set in the first place and prevent the carriage returns from being added in the first place. If you are reading from a file that uses DOS line endings, try "cleaning" it first using dos2unix.

Error in reading a multi-line string into an array?

I am using the following bash codes to want to read a multi-line string into an array. I want each array element corresponds to one line of the string.
mytext="line one
line two
line three"
IFS=$'\n' read -a lines <<<"${mytext}"
echo "len=${#lines[#]}"
for line in "${lines[#]}"
do
echo "[$line]"
done
I expect "len" should be equal to 3 and the "lines" array should be properly initialized. However, I got the following result :
len=1
[line one]
Have I used the wrong "IFS" ? What are the mistakes in the bash codes ?
Thanks in advance.
What's wrong with your solution is that read always reads a single line at a time, so telling it the IFS is a newline will make it read the entire line into the first element of the array. Each time you read you'll still overwrite the entire array. You can either build up the array iteratively:
lines=()
while read; do
lines+=("$REPLY")
done <<< "$mytext"
or by swapping the newlines for something else:
IFS='+' read -a lines <<< "${mytext//$'\n'/+}"
$ IFS=#
$ echo "${lines[*]}"
line one#line two#line three
Using mapfile (a.k.a. readarray) would be a more coherent, elegant solution, but that's only supported in Bash 4:
mapfile -t lines <<< "$mytext"
$ printf '[%s]\n' "${lines[#]}"
[line one]
[line two]
[line three]
Without the -t flag, mapfile will keep the newline attached to the array element.
This while loop should work:
arr=()
while read -r line; do
arr+=("$line")
done <<< "$mytext"
set | grep arr
arr=([0]="line one" [1]="line two" [2]="line three")
Not sure what is wrong in your case, but here is a workaround:
a=0
while read lines[$a]; do
((a++))
done <<< "${mytext}"
unset lines[$a]; #last iteration has already failed. Unset that index.

How can I assign a value to an array in Bash?

I am trying to read a list of values from a text file, hello.txt, and store them in an array.
counter=0
cat hello.txt | while read line; do
${Unix_Array[${counter}]}=$line;
let counter=counter+1;
echo $counter;
done
echo ${Unix_Array[0]}
echo ${Unix_Array[1]}
echo ${Unix_Array[2]}
I am not able to assign values to the array Unix_Array[]... The echo statement does not print the contents of the array.
There are a few syntax errors here, but the clear problem is that the assignments are happening, but you're in an implied subshell. By using a pipe, you've created a subshell for the entire while statement. When the while statement is done, the subshell exits and your Unix_Array ceases to exist.
In this case, the simplest fix is not to use a pipe:
counter=0
while read line; do
Unix_Array[$counter]=$line;
let counter=counter+1;
echo $counter;
done < hello.txt
echo ${Unix_Array[0]}
echo ${Unix_Array[1]}
echo ${Unix_Array[2]}
By the way, you don't really need the counter. An easier way to write this might be:
$ oIFS="$IFS" # Save the old input field separator
$ IFS=$'\n' # Set the IFS to a newline
$ some_array=($(<hello.txt)) # Splitting on newlines, assign the entire file to an array
$ echo "${some_array[2]}" # Get the third element of the array
c
$ echo "${#some_array[#]}" # Get the length of the array
4
If you are using Bash v4 or higher, you can use mapfile to accomplish this:
mapfile -t Unix_Array < hello.txt
Otherwise, this should work:
while read -r line; do
Unix_Array+=("$line")
done < hello.txt
The best way I found is:
declare -a JUPYTER_VENV
JUPYTER_VENV+=( "test1" "test2" "test3" )
And then consume it with:
for jupenv in "${JUPYTER_ENV[#]}"
do
echo "$jupenv"
done
Instead of this:
cat hello.txt | while read line; do
${Unix_Array[${counter}]}=$line;
let counter=counter+1;
echo $counter;
done
You can just do this:
Unix_Array=( `cat "hello.txt" `)
It’s a solution:
count=0
Unix_Array=($(cat hello.txt))
array_size=$(cat hello.txt | wc -l)
for ((count=0; count < array_size; count++))
do
echo ${Unix_Array[$count]}
done

Resources