Why would bash variables not expand in while loop [duplicate] - bash

This question already has answers here:
Forcing bash to expand variables in a string loaded from a file
(13 answers)
Closed 3 years ago.
I have a little script that reads a json file:
{
"path": "$HOME/Projects:$HOME/Github"
}
I want to read path value, split on colon : and then read out the two paths with $HOME expanded.
#!/bin/sh
path_list="$(jq -r '.path' < "$JSON_FILE" | tr ':' '\n')"
echo "$path_list" | while IFS= read -r line; do
echo "$line"
done;
The output is not what I would expect:
$HOME/Projects
$HOME/Github
Yet when I run echo "$HOME/Projects" the $HOME parameter expands fine.
Initially, I thought that I needed double quotes around the variable so I tried echo "\"${line}\"" and that just prints "$HOME/projects". I am confused. Can anyone please shed some light on this for me or point to a good tutorial on bash parameter expansion?
Regarding another SO question addressing similar issue. I do not think this is the same because that OP was asking about expanding strings loaded from a file. I do not think that is the dominant concern in my question. Other responses to this question involve using eval which I would like to because users will be entering their own inputs. Other solutions rely on external packages like gettext. I believe there should be a straight forward answer here.

Solved by adding 'eval':
#!/bin/sh
path_list="$(jq -r '.path' < "$JSON_FILE" | tr ':' '\n')"
echo "$path_list" | while IFS= read -r line; do
eval echo "$line"
done;
More info: https://unix.stackexchange.com/questions/23111/what-is-the-eval-command-in-bash

Related

how to run bash for each line in command output [duplicate]

This question already has answers here:
How can I loop over the output of a shell command?
(4 answers)
Closed 2 months ago.
i am building a bash script that is supposed to put each line of the output of one command to an variable and then run some commands on that, i am doing it like
for i in `cmd`
do
echo i=$i
lang=$(echo $i | cut -d '"' -f 6)
echo lang=$lang
#some stuff
done
my problem is that for is using space and newlines for separation to different $i's and i want it to do create only new $i's with newline delimiters cause every line may have a cupple of spaces and i want them no matter that handled as it own...
google but found nothing really helping me, only suggestions to use xargs which dosnt help me cause i need to use not one command but a cupple after creating some variables and running some if statements that desiside which command is to run if any...
If you want to read cmd's output line by line you can do it using
while loop and bash's internal read command
cmd | while IFS= read -r i
do
echo "i=${i}"
lang="$(echo "${i}" | cut -d '"' -f 6)"
echo "lang=${lang}"
#some stuff
done
Use " around a variable's de-reference to avoid problems with spaces inside it's value.

Shell that automatically trims spaces for no reason [duplicate]

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 3 months ago.
Introduction
I was trying to do some instructions on a file line by line with:
while IFS= read -r line; do
...
done < file
When I noticed that there was a problem with trailing whitespaces (for example: " a " => "a") that were automatically deleted, which is a real problem for me.
I searched in the documentation and didn't find any mention of that. And there is the same problem with printf.
Minimal example:
touch example # Create a file
echo " exa mple " >> example # Add some text
cat example # exa mple
echo $(cat example) # exa mple
rm example # Delete the file
In this example, I don't understand why echo $(cat example) doesn't have some trailing whitespaces.
And this "problem" is also here with:
while IFS= read -r line; do
echo $line # exa mple
done < example
Version:
Tested with:
zsh v5.9
bash v5.2.2
IFS= read -r line < file is correctly reading unmodified lines with leading and trailing spaces. You can confirm this by printing the variable using declare -p line.
But after you read the lines correctly, you are mangling them during your print commands. Both echo $(cat example) and echo $line have unquoted expansions, which cause the shell to word-split your lines.
Quote them to resolve the problem:
echo "$(cat example)"
echo "$line"
By the way, https://shellcheck.net/ is excellent for spotting and explaining errors like these.

How to read environment variable from the text file? [duplicate]

This question already has answers here:
Forcing bash to expand variables in a string loaded from a file
(13 answers)
Closed 1 year ago.
Hi all, I'm facing an issue that I cant read the environment variable from the text file.
Here is the content of the text file:
Blockquote
#INCLUDE
$ward/ancd/qwe
.........
.........
And the bash script
while IFS= read -r line
do
echo "$line" # It shows $ward/ancd/qwe instead of tchung/folder/main/ancd/qwe
done < "$input"
Blockquote
It should directly shows "tchung/folder/main/ancd/qwe" when echo, but it outputs $ward/ancd/qwe.
The $ward is an environment variable and it able to shows the file path in bash when echo directly. But when comes to reading text file it cant really recognize the environment variable.
Blockquote
The current solution that i can think off is replace the matched $ENVAR in the $line with the value.
repo="\$ward"
if echo "$line" | grep -q "$repo"
then
# echo "match"
line="${line/$repo/$ward}"
#echo "Print the match line : $line"
fi
Is there any other more flexible way that can recognize the environment variables during reading file without replacing the substring one by one?
Perhaps you need to evaluate the content of $line within an echo:
while IFS= read -r line
do
echo $(eval "echo $line")
done
Use envsubst:
envsubst "$input"

Can't manage to give two arguments from a fil to bash script : command not found [duplicate]

This question already has answers here:
Why does a space in a variable assignment give an error in Bash? [duplicate]
(3 answers)
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 3 years ago.
I'm new to bash script, it is interesting, but somehow I'm struggling with everything.
I have a file, separated by tab "\t" with 2 infos : a string and a number.
I'd like to use both info on each line into a bash script in order to look into a file for those infos.
I'm not even there, I'm struggling to give the arguments from the two columns as two arguments for bash.
#/!bin/bash
FILE="${1}"
while read -r line
do
READ_ID_WH= "echo ${line} | cut -f 1"
POS_HOTSPOT= echo '${line} | cut -f 2'
echo "read id is : ${READ_ID_WH} with position ${POS_HOTSPOT}"
done < ${FILE}
and my file is :
ABCD\t1120
ABC\t1121
I'm launching my command with
./script.sh file_of_data.tsv
What I finally get is :
script.sh: line 8: echo ABCD 1120 | cut -f 1: command not found
I tried a lot of possibilities by browsing SO, and I can't make it to divide my line into two arguments to be used separately in my script :(
Hope you can help me :)
Best,
The quotes cause the shell to look for a command whose name is the string between the quotes.
Apparently you are looking for
while IFS=$'\t' read -r id hotspot; do
echo "read id is: $id with position $hotspot"
done <"$1"
You generally want to avoid capturing things into variables you only use once, but the syntax for that is
id=$(echo "$line" | cut -f1)
See also Correct Bash and shell script variable capitalization and When to wrap quotes around a shell variable?. You can never have whitespace on either side of the = assignment operator (or rather, incorrect whitespace changes the semantics to something you probably don't want).
You have a space after the equals sign on lines 5 and 6, so it thinks you are looking for an executable file named echo ABCD 1120 | cut -f 1 and asking to execute it while assigning the variable READ_ID_WH to the empty string, rather than assigning the string you want to the variable.

Script: echoing lines from one file to another doesn't print '\t'. Issue [duplicate]

This question already has answers here:
Preserving leading white space while reading>>writing a file line by line in bash
(5 answers)
Closed 6 years ago.
I need to create a file by modifying some lines of a source one.
I developed a loop 'while read line; do'. Inside it, the lines I read and don't modify go just:
echo -e "$line" >> "xxxx.c"
My issue is that some of that lines start with '\t', and they won't print the output file.
Example:
while read line;
do
if echo "$line" | grep -q 'timeval TIMEOUT = {25,0};'
then
echo "$line"
fi
Any help? I've tried with the printf command also but without success.
In that case you could just remove "-e" argument from the echo command.
From echo man page:
-e enable interpretation of backslash escapes

Resources