How to fetch value of variable of variable (parameter expansion) in unix? - linux

How to fetch value of variable of variable (parameter expansion) in unix?
I have a text file(comma separated) filename='workdir.txt' as below which I am reading in unix shell script:
$AC_WORKDIR,current,FILE
$AC_WORKDIR,1 week,DIR
and so on
$AC_WORKDIR is env varriable AC_WORKDIR="/home/ascxd01/data/workdir" already defined.
My code is as below:
filename='workdir.txt'
while read line; do
work_dir=`echo $line | cut -d',' -f1`
echo "$work_dir"
done< $filename
When I am doing echo "$work_dir" its giving me $AC_WORKDIR however I want the actual value of $AC_WORKDIR which is "/home/ascxd01/data/workdir"
Please tell me how to do it.

If you drop the leading $ the indirect expansion should work normally, eg.
while read line; do
work_dir=`echo $line | cut -d',' -f1 | tr -d '$'` # delete "$"
echo "${!work_dir}"
done< $filename
The linked answer provides other maybe less good alternatives that would work, like eval "echo $work_dir".

Related

Unix Script loop through individual variables in a list and execute code

I have been busting my head all day long without coming up with a sucessfull solution.
Setup:
We have Linux RHEL 8.3 and a file, script.sh
There is an enviroment variable set by an application with a dynamic string in it.
export PROGARM_VAR="abc10,def20,ghi30"
The delimiter is always "," and the values inside vary from 1 to 20.
Inside the script I have defined 20 variables which take the values
using "cut" command I take each value and assign it to a variable
var1=$(echo $PROGARM_VAR | cut -f1 -d,)
var2=$(echo $PROGARM_VAR | cut -f2 -d,)
var3=$(echo $PROGARM_VAR | cut -f3 -d,)
var4=$(echo $PROGARM_VAR | cut -f4 -d,)
etc
In our case we will have:
var1="abc10" var2="def20" var3="ghi30" and var4="" which is empty
The loop must take each variable, test if its not empty and execute 10 pages of code using the tested variable. When it reaches an empty variable it should break.
Could you give me a hand please?
Thank you
Just split it with a comma. There are endless possibilities. You could:
10_pages_of_code() { echo "$1"; }
IFS=, read -a -r vars <<<"abc10,def20,ghi30"
for i in "${vars[#]}"; do 10_pages_of_code "$i"; done
or:
printf "%s" "abc10,def20,ghi30" | xargs -n1 -d, bash -c 'echo 10_pages_of_code "$1"' _
A safer code could use readarray instead of read to properly handle newlines in values, but I doubt that matters for you:
IFS= readarray -d , -t vars < <(printf "%s" "abc10,def20,ghi30")
You could also read in a stream up:
while IFS= read -r -d, var || [[ -n "$var" ]]; do
10_pages_of_code "$var"
done < <(printf "%s" "abc10,def20,ghi30")
But still you could do it with cut... just actually write a loop and use an iterator.
i=0
while var=$(printf "%s\n" "$PROGARM_VAR" | cut -f"$i" -d,) && [[ -n "$var" ]]; do
10_pages_of_code "$var"
((i++))
done
or
echo "$PROGRAM_VAR" | tr , \\n | while read var; do
: something with $var
done

Back slash (\) should not be printed with echo command

I have a parameter file (param.env) having the following content.
MY_PARAM=com:27}WMV\)pviZN
also, a bash file where I am fetching the value of MY_PARAM and writing into a random file.
#!/bin/bash
value=$(grep "^MY_PARAM=" param.env | cut -d '=' -f2-)
value1=$(cat param.env | grep "^MY_PARAM" | sed 's/=/ /' | awk '{print $2}')
echo $value
echo $value1
printf '%s\n' "$value"
Output:
com:27}WMV\)pviZN
com:27}WMV\)pviZN
com:27}WMV\)pviZN
However, I am expecting \ to be escaped and should not be part of the output.
I am also not allowed to edit the param.env.
Expected output:
com:27}WMV)pviZN
You could source the file, then the string will behave as if you'd assigned it like that in an interactive shell:
$ (. param.env; echo "$MY_PARAM")
com:27}WMV)pviZN
I've put the commands in a subshell so they don't pollute the environment.

Linux Shell Script: extract values from string in specified manner

I have one variable contain values like:
USER1:USER2,USER3:USER4,USER5:USER6
I want to extract values like USER1,USER3,USER5
For Example:
VALUE = USER1:USER2,USER3:USER4,USER5:USER6
how I echo to extract like this
USER1,USER3,USER5
#!/bin/bash
string=USER1:USER2,USER3:USER4,USER5:USER6
IFS=', ' read -r -a array <<< "$string"
output=
for kv in ${array[#]}; do
key=$(echo $kv | cut -d':' -f1)
output="$output,$key"
done
output=$(echo $output | cut -c 2-)
echo $output

Reading and comparing column in .txt file in bash

I got .txt file which its content is
5742060626,Ms.Pimpan Tantivaravong,Female
5742065826,Ms.Kaotip Tanti,Female
-
I create an interface script to add list in this file
First, I have to compare the input id with the exitsting id in a list.
I use cut command to read only 1st column of .txt file.
But,I got a problem when I am trying to compare it.
Here is my code.
-
!/bin/bash
#
datafile='student-2603385.txt'
while read p;
do
if [ "$id" == (echo $p | cut -d, -f1) ]
then
echo 'duplicate id'
fi
done <$datafile
-
could anyone suggest me, how should I do?
Thank you
Your script has numerous quoting bugs, always quote variable expansion when the variable contains a file name, it is also expected when you want to avoid word splitting and pathname expansion by shell.
Letting that aside, in if [ "$id" == (echo $p | cut -d, -f1) ]:
You need command substitution, $() around echo ... | cut ..., not a subshell ()
you also need quotes around $() to prevent word splitting (and pathname expansion)
== is bash-ism, not defined by POSIX, just a reminder
try to use [[ as much as possible, being a shell keyword [[ handles word splitting
So with test ([):
if [ "$id" == "$(echo "$p" | cut -d, -f1)" ]
better:
if [[ $id == $(echo "$p" | cut -d, -f1) ]]

BASH tr command

Id like to convert it to uppercase for the simple purpose of formatting so it will adhere to a future case statement. As I thought case statements are case sensitive.
I see all over the place the tr command used in concert with echo commands to give you immediate results such as:
echo "Enter in Location (i.e. SDD-134)"
read answer (user enters "cfg"
echo $answer | tr '[:lower:]' '[:upper:]' which produced
cfg # first echo not upper?
echo $answer #echo it again and it is now upper...
CFG
This version doesn't require bash, but uses a pipe:
read -p "Enter in Location (i.e. SDD-134) " answer
answer=$(echo "$answer" | tr '[:lower:]' '[:upper:]')
echo "$answer"
And if you're using bash and don't care about portability you can replace the second line with this:
answer="${answer^^}"
Check the "Parameter Expansion" section of bash's man page for details.
Echoing a variable through tr will output the value, it won't change the value of the variable:
answer='cfg'
echo $answer | tr '[:lower:]' '[:upper:]'
# outputs uppercase but $answer is still lowercase
You need to reassign the variable if you want to refer to it later:
answer='cfg'
answer=$(echo $answer | tr '[:lower:]' '[:upper:]')
echo $answer
# $answer is now uppercase
In bash version 4 or greater:
answer=${answer^^*}
It is not clear what you are asking, but if you are trying to convert the user input to uppercase, just do:
sed 1q | tr '[:lower:]' '[:upper:]' | read answer
In shells that do not run the read in a subshell (eg zsh), this will work directly. To do this in bash, you need to do something like:
printf "Enter in Location (i.e. SDD-134): "
sed 1q | tr '[:lower:]' '[:upper:]' | { read answer; echo $answer; }
After the subshell closes, answer is an unset variable.
good and clear way to uppercase variable is
$var=`echo $var|tr '[:lower:]' '[:upper:]'`
Note Bene a back quotes

Resources