Coloring a variable in "read -p" command - linux

I would like to color a variable in the "read -p" command. In another topic i found
a way to color the text string like this:
read -p $'\e[31mFoobar\e[0m: ' <= works
But if I put a variable instead of 'Foobar' the value is not shown because the single quotes are preventing the call of the variable $mmd.
read -p $'\e[31m $mmd \e[0m: ' <= doesnt ork
Do you know a way to make this work?
I tried:
read -p $'\e[31m $mmd \e[0m: ' <= doesnt work
read -p $"\e[31m $mmd \e[0m: " <= doesnt work

You can terminate and restart the escape sequence, thus moving the variable expansion outside, as per the following transcript:
pax:~> mmd="Enter something"
pax:~> read -p $'\e[31m'"${mmd}"$'\e[0m: '
Enter something: hello<enter>
pax:~> echo ${REPLY}
hello

Related

Assigning one variable to another in Bash

ip="192.168.1.1"
if [ -n "$(ip = 192.168.1.1)" ];
then
IPADDR=$(ip addr show |grep 'inet '|grep -v 127.0.0.1 |awk '{print $2}'| cut -d/ -f1)
else
"${ip}"="${IPADDR}"
fi
echo "${IPADDR}"
Im trying to assigning ip="192.168.1.1" to variable IPADDR
the error im geting atm is
Object "=" is unknown, try "ip help".
./test: line 7: 192.168.1.1=: command not found
Here ...
if [ -n "$(ip = 192.168.1.1)" ];
... you are executing the command ip, passing arguments = and 192.168.1.1, and capturing its standard output. These are not valid arguments for that command, so ip emits an error message to its standard error, but nothing to its standard output.
The test [ -n "$(ip = 192.168.1.1)" ] evaluates whether the captured output is non-empty, so this test fails, and consequently, the else block is executed. Here ...
"${ip}"="${IPADDR}"
... is not a variable assignment but rather a command, because the text to the left of the = is not (just) an identifier. The IPADDR variable is unset or null, so that expands to 192.168.1.1=. The shell reports that there is no command of that name.
It's hard to be sure what you were really trying to accomplish, but going with the question title, if you want to assign a value to a variable then the syntax is
variable_name=value
The variable_name must be an identifier. The value is subject to expansion and quote removal, but not word splitting, so either of these would work for what you appear to be trying to do
ip="${IPADDR}"
or
ip=${IPADDR}
. With that said, the code does not make sense, because it does not assign a value to variable IPADDR before attempting that assignment.
Earlier, it is possible that you meant
if [ "$ip" != 192.168.1.1 ]
... which tests whether the value of variable $ip, considered as a string, is equal to the string 192.168.1.1. Even then, however, the code does not make sense overall.

Inserting the date into a "MAIL" message body in a BASH script

I have a relatively simple BASH script to send mail from my Raspberry Pi. The first argument is the Subject line and the second is a string of data files to be attached.
It is basically working when I specify the message body as a file (line 6). But if I try to create a text sting containing the date as the message body it fails (line7). Here is my script:
#!/bin/bash
#echo $2
# To
TO="me#hotmail.com"
# Message
MESSAGE="output/MessageBody.txt"
MESSAGEx="Midnight `date '+%Y-%m-%d %H:%M:%S %Z'` Pi report"
echo $MESSAGE
echo $MESSAGEx
temp=$(echo $2 | tr ";" "\n")
declare -a attargs
for att in $temp; do
attargs+=( "-A" "$att" )
done
# Sending email using /bin/mail
/usr/bin/mail -s "$1" "$TO" ${attargs[#]} < $MESSAGEx
Here is the output from this command
/usr/pgms/sendtome.sh "test message" "/mnt/usbdrive/output/JSONstart.txt;/mnt/usbdrive/output/Outback_error.log;/mnt/usbdrive/output/OutbackReaderPrint.txt"
when I specify MESSAGEx as the message body:
/mnt/usbdrive/output/MessageBody.txt
Midnight 2019-08-14 07:40:31 MDT Pi report
/usr/pgms/sendtome.sh: line 22: $MESSAGEx: ambiguous redirect
If I use MESSAGE, ie the text file reference, it works.
How can it create a message body text paragraph which contains the date or some other item? Thanks....RDK
There's a number of issues here.
You should generally quote strings. Without quoting, the string after < is split (hence the error message) and the array you took so much care to collect will lose its purpose.
The thing after < needs to be the name of a file. In Bash you can use a here string <<<"$MESSAGEx" but the common and simple portable solution is to echo (or better printf) its value into a pipe.
You should prefer lower case for your private variable names, but this is mainly a stylistic recommendation. (There are reserved variables like PATH and SHELL which you really don't want to clobber; POSIX reserves upper case variable names for system use.)
Here's a refactoring which attempts to address these concerns.
#!/bin/bash
to="me#hotmail.com"
# Message
#msgfile="output/MessageBody.txt"
msgbody="Midnight `date '+%Y-%m-%d %H:%M:%S %Z'` Pi report"
#echo "$msgfile"
#echo "$msgbody"
declare -a attargs
for att in $(echo "$2" | tr ";" "\n"); do
attargs+=( "-A" "$att" )
done
/usr/bin/mail -s "$1" "${attargs[#]}" "$to"<<< "$msgbody"
Perhaps a better design would be to just shift the first argument and then use "$#" as the list of files to attach.

If output of bash command is empty, do something

Hi I am new to bash so please excuse me if I have a really silly/easy question. I am writing a script which allows the user to change their region (for wireless). What I am wanting to do is put a check in place, so if they type in an incorrect value, it brings up the prompt again to input the region. I want to do this by checking if the output of the command sudo iw reg set $reg, if it is a correct input, there is no output. But if it is a wrong input, it gives an error message. I tried to do this but im getting an error:
#!/bin/bash
echo "Please set a region: "
read reg
if [(sudo iw reg set $reg) -ne 0]; then
echo "Please set a valid region: "
read reg
else
echo "Setting reg as $reg"
sudo iw reg set $reg
fi
Thanks in advance
You can use the -z test, type help test in Bash to learn more (test is the same as the [ command).
You should only call iw reg set once, unless it fails.
echo "Please set a region: "
while true # infinite loop
do
# read in the region:
read reg
# try the command, and catch its output:
output=$( sudo iw reg set "$reg" 2>&1 )
if [ -z "$output" ]
then
# output is empty - success - leave the loop:
break
else
# output is non-empty - continue:
echo "Please set a valid region. "
fi
done
This snippet checks the success condition you gave in your question (empty output), but it should be noted that usually exit codes should be used if possible.
Note the 2>&1 operator redirecting stderr to stdout so any output on either file descriptor will be considered a failure.
You can use read in a while loop:
while read -r -p "Please set a valid region: " reg; do
[[ -z "$(sudo iw reg set $reg)" ]] && break
done
help read gives this:
-r do not allow backslashes to escape any characters
-p prompt output the string PROMPT without a trailing newline before
attempting to read
$(...) is command substitution to execute a command and return output
-z returns true when given string argument (output of iw command) is empty

how to declare variable name with "-" char (dash ) in linux bash script

I wrote simple script as follow
#!/bin/bash
auth_type=""
SM_Read-only="Yes"
SM_write-only="No"
echo -e ${SM_Read-only}
echo -e ${SM_Write-only}
if [ "${SM_Read-only}" == "Yes" ] && [ "${SM_Write-only}" == "Yes" ]
then
auth_type="Read Write"
else
auth_type="Read"
fi
echo -e $auth_type
And when i execute it i got following output with errors.
./script.bash: line 5: SM_Read-only=Yes: command not found
./script.bash: line 6: SM_write-only=No: command not found
only
only
Read
Any one know correct way to declare the variable with "-" (dash)?
EDIT:
have getting response from c code and evaluate the variables for example
RESP=`getValue SM_ Read-only ,Write-only 2>${ERR_DEV}`
RC=$?
eval "$RESP"
from above scripts code my c binary getValue know that script want Read-only and Write-only and return value to script.So during eval $RESP in cause error and in my script i access variable by
echo -e ${SM_Read-only}
echo -e ${SM_Write-only}
which also cause error.
Rename the variable name as follows:
SM_Read_only="Yes"
SM_write_only="No"
Please, don't use - minus sign in variable names in bash, please refer to the answer, on how to set the proper variable name in bash.
However if you generate the code, based on others output, you can simply process their output with sed:
RESP=$(getValue SM_ Read-rule,Write-rule 2>${ERR_DEV}|sed "s/-/_/g")
RC=$?
eval "$RESP"
- is not allowed in shell variable names. Only letters, numbers, and underscore, and the first character must be a letter or underscore.
I think you cant have a dash in your variables names, only letters, digits and "_"
Try:
SM_Read_only
Or
SM_ReadOnly

CSV Bash loop Issue with Variables

I have a csv file which im trying to loop through with the purpose to find out if an User Input is found inside the csv data. I wrote the following code which sometimes works and others doesn't. It always stops working when I try to compare to a 2+ digit number. It works OK for numbers 1 through 9, but once u enter lets say 56 , or 99 or 100, it stops working.
the csv data is comma delimited, i have about 300 lines they are just like this.
1,John Doe,Calculus I,5.0
1,John Doe,Calculus II,4.3
1,John Doe,Physics II,3.5
2,Mary Poppins,Calculus I,3.7
2,Mary Poppins,Calculus II,4.7
2,Mary Poppins,Physics I,3.7
Data is just like that, all the way down until ID #100 for a total of 300 lines. Both the sh file and csv file are in the same folder, I'm using a fresh installation of Ubuntu 12.04.3, using gedit as the text editor.
I tried Echoing the variables ID and inside the IF conditionals but it doesn't behave the way it should when testing for the same value. Could someone point me out in the right direction. Thanks
Here's the code:
#s!/bin/bash
echo "enter your user ID";
read user;
INPUT_FILE=notas.csv
while IFS="," read r- ID name asignature final;
do
if [$ID = $user]; then
userType=1;
else
userType=2;
fi
done < notas.csv
Well, your code as written has a few issues.
You have r- instead of -r on the read line - I assume that's a typo not present in your actual code or you wouldn't get very far.
Similarly, you need space around the [...] brackets: [$ID is a syntax error.
You need to quote the parameter expansions in your if clause, and/or switch bracket types. You probably make it a numeric comparison as #imp25 suggested, which I would do by using ((...)).
You probably don't want to set userType to 2 in an else clause, because that will set it to 2 for everyone except whoever is listed last in the file (ID 100, presumably). You want to set it to 2 first, outside the loop. Then, inside the loop when you find a match, set it to 1 and break out of the loop:
userType=2
while IFS=, read -r ID name asignature final; do
if (( $ID == $user )); then
userType=1;
break
fi
done < notas.csv
You could also just use shell tools like awk:
userType=$(awk -F, -vtype=2 '($1=="'"$user"'") {type=1}; END {print type}' notas.csv)
or grep:
grep -q "^$user," notas.csv
userType=$(( $? + 1 ))
etc.
You should quote your variables in the if test statement. You should also perform a numeric test -eq rather than a string comparison =. So your if statement should look like:
if [[ "$ID" -eq "$user" ]]

Resources