Parse comma separated string of numbers into variables (scripting) bash [duplicate] - bash

This question already has answers here:
How do I split a string on a delimiter in Bash?
(37 answers)
Closed 4 years ago.
The post marked as duplicate above is similar, however is not sufficient for the use case. The below answers show a minimalist use of the read command to put parsed input for a known length of delimiter separated values into helpfully-named variables. For instance, if I read all four vars into $STATEMENTS,$BRANCHES,$FUNCTIONS,$LINES - a loop is not ideal as it adds a minimal of loop index awareness or 4 more lines to put each array var into a helpfully named var.
I have a list of comma separated numbers in a file:
26.16,6.89,23.82,26.17
I'd like to read these 4 numbers into helpfully named separate variable names - there will never fewer or more than 4 numbers.
Thanks for any help!

You'll need read builtin. The input stream, and variables to read can vary, based on your personal preferences. For instance,
IFS=,
LIST=1,2,3,4
read a b c d <<<$LIST
echo $a ; echo $b ; echo $c ; echo $d

Related

Convert string to an array in shell script [duplicate]

This question already has answers here:
Bash: Split string into character array
(20 answers)
Closed 4 months ago.
How can ı convert a string to an array in shell script?
For example i want to put "apple" to an array.
array[0] = a
array[1]=p
array[2]=p
array[3]=l
array[4]=e
I tried a lot of things but none of them worked. I tried to use IFS but i have no space or comma in my word so it didn't work.
Parameter expansion is relevant here: ${#var} gives you the number of characters in var, and ${var:start:len} takes len characters from var, starting at position start.
Combine those two techniques and you get:
#!/usr/bin/env bash
string='apple'
array=( )
for ((i=0; i<${#string}; i++)); do
array[$i]=${string:i:1}
done
declare -p array
...which emits as output:
declare -a array=([0]="a" [1]="p" [2]="p" [3]="l" [4]="e")

Split string into array in shell script based on regex delimiter [duplicate]

This question already has answers here:
Split a string only by spaces that are outside quotes
(4 answers)
Closed 2 years ago.
I have a string variable called JAVA_OPTS with various parameters in shell script.
-Dmaven.repo.local=/home/wangc/.m2/repository -Dtestparameter="some spaces" --add-exports=java.base/sun.nio.ch=ALL-UNNAMED
I'd like to split it into an array based on spaces, but not the space defined in escaped double quotes. For example I'd like to see an array with 3 elements:
-Dmaven.repo.local=/home/wangc/.m2/repository
-Dtestparameter="some spaces"
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
I have tried
IFS=' ' read -r -a array <<< "$JAVA_OPTS"
But it can't tell the different space between double quotes, and return a four elements array as:
-Dmaven.repo.local=/home/wangc/.m2/repository
-Dtestparameter="some
spaces"
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
Why do you require a regex solution? Getting the shell itself to parse this is significantly easier.
array=(-Dmaven.repo.local=/home/wangc/.m2/repository -Dtestparameter="some spaces" --add-exports=java.base/sun.nio.ch=ALL-UNNAMED)
Detouring the values via a string variable $JAVA_OPTS is precisely the wrong thing to do here, and makes the problem signicicantly harder.

Double square braces in Bash [duplicate]

This question already has answers here:
BASH regexp matching - including brackets in a bracketed list of characters to match against?
(4 answers)
Closed 5 years ago.
I need to match some variables defined in a config file against an input file in bash and replace the variable with config file input.
Config file
var1=value1
var2=value2
input file
My user value is [[var1]] and
some lines which does not have configuration variables
My client value is [[var2]]
some lines which does not have configuration variables
var1 and var2 in line 1 and 3 above must be replaced by the value in config file
rest of the lines remains same.
I am able to read config in an associative array say mapVals and input file to an array say inpArray.
Now when I am matching in a loop with below code.
for key in "${!mapVals[#]}"
do
match=\[\[$key\]\]
echo $match
let index=0
for line in "${inpArray[#]}"
do
if [[ $line =~ $match ]];
then
echo $line
fi
index=$(($index+1))
done
done
I am getting match for both line1 and line 3 for both of the [[var1]] and [[var2]] matches.
the output looks like
[[var1]]
My user value is [[var1]] and
My client value is [[var2]]
[[var2]]
My user value is [[var1]] and
My client value is [[var2]]
What should be the way for an exact match and replace.
Please comment if duplicate.
I got the answer here
so for square braces we need to use escape []
the regex for [[var1]] is => [\[][\[]var1]]

Print multiple lines from a Text Document - Bash [duplicate]

This question already has answers here:
Losing newline after assigning grep result to a shell variable
(4 answers)
Closed 7 years ago.
I have a program that is trying to print multiple lines from a text document. I have my main bash program, and I am using the line:
Multlines=`</Users/$USER/Documents/text.txt`
echo $Multlines
Where text.txt may look something like
John
Smith
but the echo prints John Smith where I want it to print it on different lines.
How do I print it out that way?
To preserve the newline characters in the variable when printing with echo, you need to double quote it:
echo "$Multlines"
You could also just use cat instead of echo, assuming you had it available to you.

Read line by line from standard input Bash [duplicate]

This question already has answers here:
Read line by line in Bash script
(7 answers)
Closed 4 years ago.
I'm studying bash language and an exam track says this:
It should read one input (from standard input) at a time (each entry
is a string and then ends with a newline).
My questions are two:
How do I read line by line from standard input in Bash? Until now I used "read string" but I do not think that it reads a line at a time.
I do not know if this is a stupid question , but once created the script how can I give more lines to the script as input (read from standard input of course). For example from stdin I insert two lines (hello and world). How do I give to the bash script these two lines?
How do I read line by line from standard input in Bash? Until now I
used "read string" but I do not think that it reads a line at a time.
The prototype for read is:
read [options] name[s ...]
read will read a line of input into name name1 name2 ... splitting the line based on the contents of the Internal Field Separator (IFS). The default for IFS is ' \t\n' (that is space tab newline). If you only provide a single variable to read, you will read the entire line into that variable (unless you have set a new delimiter with the -d option to read). If you provide more than one variable, (e.g. read -r name name1) word splitting will occur based on the current value of IFS. Meaning if you provide the string hello world to:
read -r name
name="hello world". On the other hand, if you provide the same string to:
read -r name name1
name="hello", name1="world". What if you have excess words in the line but only 2 variables? Say your string is now "hello big wide world", what happens with:
read -r name name1
name="hello", name1="big wide world". The words in string are assigned to your variables in order and if there are insufficient variables to hold each word in the string, the last variable will contain all remaining words in the string not previously assigned.
You change how word splitting occurs by altering IFS. Take a close look at the answer provided by anubhava for an example. You are free to specify any character you would like the words to be split on. (helpful in say parsing a csv file to set IFS=$',\n' and have the words split on ',' instead of space)
To ensure you read an entire line into a variable, you can provide only a single variable to read and set IFS='$\n' to ensure word splitting only occurs on newline. (Note: providing the change as part of the while loop limits the IFS alteration to the scope of that loop. For example:
while IFS='$\n' read -r line; do
# do whatever with line
done
Will ensure that each line on stdin will be read into line while preserving normal word-splitting outside the loop. Inside the loop you can then add each line to an array as anubhava shows in his answer. (to preserve all whitespace IFS= is used)
You can do something like this:
# array to hold all lines read
lines=()
# read all lines in lines array
while IFS= read -r line; do
lines+=( "$line" )
done < file
# read 3 more lines from stdin
for ((i=0; i<3; i++)); do
read -rp "Enter a line: " line
lines+=( "$line" )
done

Resources