Shell - Taking the input from the user from each line - arrays

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

Related

Append to an array within a loop

I have this type of script, which asks for the user input and then stores it on an indexed array like:
#!/bin/bash
declare -a ka=()
for i in {1..4};
do
read -a ka > ka();
done
echo ${ka[#]}
I can't manage to append the read statement to the array.
When you run read -r -a arrayname, the entire array is rewritten starting from the very first item; it doesn't retain any of the prior contents.
Thus, read into a temporary array, and append that temporary array to your "real" / final one:
#!/usr/bin/env bash
case $BASH_VERSION in '') echo "ERROR: must be run with bash" >&2; exit 1;; esac
declare -a ka=()
for i in {1..4}; do
# only do the append if the read reports success
# note that if we're reading from a file with no newline on the last line, that last
# line will be skipped (on UNIX, text must be terminated w/ newlines to be valid).
read -r -a ka_suffix && ka+=( "${ka_suffix[#]}" )
done
# show current array contents unambiguously, one-per-line (echo is _very_ ambiguous)
printf ' - %q\n' "${ka[#]}"

number input in shell

I want to get inputs(numbers) from user "last". And after that I will use numbers for evaluation. But my program doesn't work correctly.
Here is my code :
echo "Enter numbers until -last- "
while read line
do
array=("${array[#]}" $line)
if [ "$array[-1]" != "last" ]
then
break
fi
done
......
.....
echo "average numbers of this blablabla " #this part is correct
It works correctly when I use space button but I have to use enter button. And it doesn't accept "last" input.
How can I implement it?
This loop populates inputArray with the lines you enter (no checking that they're actually numbers) up until you enter a line containing only last:
inputArray=()
echo "Enter numbers until -last- "
while read line
do
if [ "$line" = "last" ]
then break
fi
inputArray+=("$line")
done
echo "${inputArray[#]}"
You can take it from there. Note that the entry isn't added to the array until you know it isn't last.
Some people will insist you should use read -r instead of just read; feel free to ignore them once you know what you're risking (see read in the Bash manual).

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.

Bash script array to csv

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.

Resources