Create conditional bash script code - regex

I use the following code to load some text file with emails
and create users in the system with user password.
the text file contain emails like following
abc#gmail.com
BDD#gmail.com
ZZZ#gmail.com
In case the name is coming with upper case I convert it to lower case, I was able to make it work.
Now I need to support another input instead of email
e.g.
P123456
Z877777
but now I dont want for this type of input to convert it to lower case
someting like
if(emailpattern )
convert to lower
else
Not
This is the code which works but I failed to make it work...
for user in $(cat ${users} | awk -F";" '{ print $1 }'); do
user=$(echo ${user} | tr "[:upper:]" "[:lower:]")
log "cf create-user ${user} ${passwd}"
#Here we are creating email user in the sys
cf create-user ${user} ${passwd} 2>&1 |
tee -a ${dir}/${scriptname}.log ||
{ log "ERROR cf create-user ${user} failed" ;
errorcount=$[errorcount + 1]; }
done

You can use:
while IFS= read -r user; do
# convert to lowercase only when $user has # character
[[ $user == *#* ]] && user=$(tr "[:upper:]" "[:lower:]" <<< "$user")
log "cf create-user ${user} ${passwd}"
cf create-user ${user} ${passwd} 2>&1 |
tee -a ${dir}/${scriptname}.log ||
{ log "ERROR cf create-user ${user} failed" ;
errorcount=$[errorcount + 1]; }
done < <(awk -F ';' '{ print $1 }' "$users")

Assumptions:
input file consists of email addresses or names, each on a separate line
email addresses are to be converted to lower case
names are to be left as is (ie, no conversion to lower case)
all of the log/cf/tee/errorcount code functions as desired
Sample input file:
$ cat userlist
abc#gmail.com
BDD#gmail.com
ZZZ#gmail.com
P123456
Z877777
We'll start by using awk to conditionally convert email addresses to lower case:
$ awk '/#/ {$1=tolower($1)} 1' userlist
abc#gmail.com
bdd#gmail.com
zzz#gmail.com
P123456
Z877777
first we'll run the input file (userlist) through awk ...
/#/ : for lines that include an email address (ie, contains #) ...
$1=tolower($1) : convert the email address (field #1) to all lowercase, then ...
1 : true for all records and implies print all inputs to output
Now pipe the awk output to a while loop to perform the rest of the operations:
awk '/#/ {$1=tolower($1} 1}' userlist | while read user
do
log "cf create-user ${user} ${passwd}"
#Here we are creating email user in the sys
cf create-user ${user} ${passwd} 2>&1 |
tee -a ${dir}/${scriptname}.log ||
{ log "ERROR cf create-user ${user} failed" ;
errorcount=$((errorcount + 1)) ;
}
done
updated to correctly increment errorcount by 1

bash can lower-case text:
while IFS= read -r line; do
[[ $line == *#* ]] && line=${line,,}
# do stuff with "$line"
done

Related

Bash break down IP range into variables

I'm trying to write a bash script which will do the following
Read a file that has IP addresses stored in it
ips.txt
Take those IP addresses and break them into 3 variables that write to their own files
Files
thrid_octave.txt
last_digit_third_octave.txt
last_octive.txt
Variables
thrid_octave
last_digit_third_octave
last_octive
EX: 12.34.117.88
thrid_octave = 111
last_digit_third_octave = 7
last_octive = 88
Below is how i intend to use those variables
#!/bin/bash
domain="$(cat domains.txt)"
ip="$(cat ips.txt)"
last_number_third_octete="$(cat last_number_third_octete.txt)"
thrid_octive="$(cat thrid_octive.txt)"
last_octive="$(cat last_octive.txt)"
while read -r domain <&3 && read ip <&4 && read last_number_third_octete <&5 && read thrid_octive <&6 && read last_octive <&7 &&;
do
echo "processing $domain";
"##################################### $domain ######################################################"
smtp-listener $ip\n
<virtual-mta $domain.c$last_number_third_octete.$last_octive>
smtp-source-host $ip mailer1-vmta-plat-$thrid_octive-$last_octive.$domain
</virtual-mta>
<virtual-mta-pool $domain.p>
virtual-mta $domain.c$thrid_octive-$last_octive
</virtual-mta-pool>
\n\n
done 3<domains.txt 4<ips.txt 5<last_number_third_octete.txt 6<thrid_octive.txt 7<last_octive.txt
echo "All Set"
You could try to use cut, like this:
ip="12.34.117.88"
thrid_octave=`echo $ip | cut -d\. -f3`
last_digit_third_octave=`echo $ip | cut -d\. -f3 | cut -c 3`
last_octive=`echo $ip | cut -d\. -f4`

sed command issues

Background
Original json (test.json): {"rpc-password": "password"}
Expected changed json: {"rpc-password": "somepassword"}
replace_json_str is a function used to replace password with somepassword using sed.
replace_json_str() {
x=$1
sed -i -e 's/\({ "'"$2"'":\)"[^"]*" }/\1"'"$3"'" }/g' $x
}
Unit test: replace_json_str test.json rpc-password somepassword
Issue
After running the above test, I get a file named test.json-e and the contents of the file is the same as before the test was ran, why?
there is a handy command line json tool called jq
cat input.json
{"rpc-password": "password"}
cat update_json.sh
givenkey=$1
givenvalue=$2
inputfile=input.json
outfile=output.json
cat $inputfile | jq . # show input json
jq --arg key1 "$givenkey" --arg val1 "$givenvalue" '.[$key1] = $val1' "$inputfile" > "$outfile"
cat "$outfile" | jq . # render output json
keep in mind jq can handle multiple such key value updates ... execute it
update_json.sh rpc-password somepassword
{
"rpc-password": "password"
}
{
"rpc-password": "somepassword"
}
Depends on which sed you're using.
The command you ran will work as expected with GNU sed.
But BSD sed does not allow for an empty argument to -i, and if you ran the same command, it will use the next argument, -e, as the backup file.
Also, the positioning of the spaces in your pattern don't match your example JSON.

Bash variable substitution in a function

I have a function read_command defined as:
function read_command {
local __newline __lines __input __newstr __tmp i;
exec 3< "$*";
__newline=$'\n';
__lines=();
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
echo "$__line";
__lines+=("$__line");
done
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
read -e -p "${__line#*:}$PS2" __input;
local ${__line%%:*}="$__input";
done
__command="";
for i in "${__lines[#]}"; do
__tmp=$(echo "${i}");
__command="${__command} ${__newline} ${__tmp}";
done
echo -e "$__command";
}
In the current directory there is a file named "test", with the following
content:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
####
a: name of friend a
b: name of friend b
####
In the terminal, the command executed is
read_command test
With no input, I am expecting the output of the last statement to be:
greet Bob
greet Jim
But what I get is:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
What is wrong here?
Edit: As suggested by David, adding eval works in some cases except the following one.
j=1;i="export DISPLAY=:0 && Xephyr :${j}&";k=$(eval echo "$i");
echo $k
export DISPLAY=:0
I am expecting k to be "export DISPLAY=:0 && Xephyr :1&", what's wrong here?
Edit: I tried with the following
k=$(eval "echo \"$i\"")
This is the link to the script I am working on.
https://gist.github.com/QiangF/565102ba3b6123942b9bf6b897c05f87
During the first while loop, in echo "$__line", you have __line='greet ${a:-"Bob"}'. When you try to print that, Bash won't be expanding ${a:-"Bob"} into Bob. (Even if you remove the quotes around $__line this won't happen.) To get that effect, you need to add eval, as in, e.g., eval echo "$__line". Unfortunately eval comes with its can of worms, you have to start worrying about interactions between quoting levels and such.

I get syntax error when i call script from c++ program

I'm trying to write a program that will allow easier management of Arduino projects. So I wrote bash script that creates all the necessary folders and files for me and when I execute it I runs like champ. Because I want to change directory in the working terminal inside the script I run script like this
. ./initialize.sh
This is also working great, but because I am writing C++ program, sourcing this script from program is giving me headache.
So inside a program I run this script like this:
system(". /usr/lib/avrduino/script/initialize.sh");
and then when I run the program I get this error:
sh: 25: /usr/lib/avrduino/script/initialize.sh: Syntax error: "(" unexpected (expecting "}")
Running the script from the program like this:
system("/usr/lib/avrduino/script/initialize.sh");
works without error but it runs in subshell.
Syntax error points to this line in script
options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")
How come that when I run this script outside of the program it's working like champ, but run this script from program and you have a problem ?
EDIT:
Script code
#!/bin/bash
BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
BROWN='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
LGRAY='\033[0;37m'
DGRAY='\033[1;30m'
LRED='\033[1;31m'
LGREEN='\033[1;32m'
YELLOW='\033[1;33m'
LBLUE='\033[1;34m'
LPURPLE='\033[1;35m'
LCYAN='\033[1;36m'
WHITE='\033[1;37m'
NC='\033[0m'
makefile()
{
BOARD="default"
PS3='Chose your board: '
options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")
select opt in "${options[#]}"
do case $opt in
"uno") BOARD="uno"
cp -r /usr/lib/avrduino/data/boards_info/uno/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"mega") BOARD="mega"
cp -r /usr/lib/avrduino/data/boards_info/mega/board-info.h .
F_CPU="16000000UL"
;;
"mega2560") BOARD="mega2560"
cp -r /usr/lib/avrduino/data/boards_info/mega2560/board-info.h .
F_CPU="16000000UL"
;;
"atmega8") BOARD="atmega8"
cp -r /usr/lib/avrduino/data/boards_info/atmega8/board_-nfo.h .
MCU="atmega8"
F_CPU="16000000UL"
;;
"atmega168") BOARD="atmega168"
cp -r /usr/lib/avrduino/data/boards_info/atmega168/board-info.h .
MCU="atmega168"
F_CPU="16000000UL"
;;
"atmega328") BOARD="atmega328"
cp -r /usr/lib/avrduino/data/boards_info/atmega328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"pro") BOARD="pro"
cp -r /usr/lib/avrduino/data/boards_info/pro/board-info.h .
MCU="unknow"
F_CPU="16000000UL"
;;
"pro5v") BOARD="pro5v"
cp -r /usr/lib/avrduino/data/boards_info/pro5v/board-info.h .
MCU="unknown"
F_CPU="16000000UL"
;;
"pro328") BOARD="pro328"
cp -r /usr/lib/avrduino/data/boards_info/pro328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"pro5v328") BOARD= "pro5v328"
cp -r /usr/lib/avrduino/data/boards_info/pro5v328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
*)
echo "Error : Input is not valid"
echo "Exiting..."
return 1
;;
esac
break
done
[ -e Makefile ] && rm Makefile
read -p "Do you want to configure your Makefile settings [Y/n]: " CONFIGURE
if { [ "$CONFIGURE" == "Y" ] || [ "$CONFIGURE" == "y" ]; }; then
read -p "Enter your MCU: " MCU
read -p "Enter F_CPU: " F_CPU
fi
read -p "Enter ARDUINO_PORT: " ARDUINO_PORT
echo "ARDUINO_DIR = /usr/share/arduino">>Makefile
echo "BOARD_TAG = $BOARD">>Makefile
echo "ARDUINO_PORT = $ARDUINO_PORT">>Makefile
echo "NO_CORE = 1">>Makefile
echo "AVRDUDE_ARD_PROGRAMMER = arduino">>Makefile
echo "HEX_MAXIMUM_SIZE = 30720">>Makefile
echo "AVRDUDE_ARD_BAUDRATE = 115200">>Makefile
echo "#ISP_LOW_FUSE = 0xFF">>Makefile
echo "#ISP_HIGH_FUSE = 0xDA">>Makefile
echo "#ISP_EXT_FUSE = 0x05">>Makefile
echo "#ISP_LOCK_FUSE_PRE = 0x3F">>Makefile
echo "#ISP_LOCK_FUSE_POST = 0x0F">>Makefile
echo "MCU = $MCU">>Makefile
echo "F_CPU = $F_CPU">>Makefile
echo "VARIANT = standard">>Makefile
echo "ARDUINO_LIBS =">>Makefile
echo "include /usr/share/arduino/Arduino.mk">>Makefile
echo "$BOARD|$MCU|" >> .avrduino.txt
clear
echo -e "${LGREEN}Makefile settings${NC}"
echo -e "${LBLUE}ARDUINO_DIR = ${LRED}/usr/share/arduino ${NC}"
echo -e "${LBLUE}BOARD_TAG = ${LRED}$BOARD${NC}"
echo -e "${LBLUE}ARDUINO_PORT = ${LRED}$ARDUINO_PORT${NC}"
echo -e "${LBLUE}NO_CORE = ${LRED}1${NC}"
echo -e "${LBLUE}AVRDUDE_ARD_PROGRAMMER = ${LRED}arduino${NC}"
echo -e "${LBLUE}HEX_MAXIMUM_SIZE = ${LRED}30720${NC}"
echo -e "${LBLUE}AVRDUDE_ARD_BAUDRATE = ${LRED}115200${NC}"
echo -e "${DGRAY}#ISP_LOW_FUSE = ${RED}0xFF${NC}"
echo -e "${DGRAY}#ISP_HIGH_FUSE = ${RED}0xDA${NC}"
echo -e "${DGRAY}#ISP_EXT_FUSE = ${RED}0x05${NC}"
echo -e "${DGRAY}#ISP_LOCK_FUSE_PRE = ${RED}0x3F${NC}"
echo -e "${DGRAY}#ISP_LOCK_FUSE_POST = ${RED}0x0F${NC}"
echo -e "${LBLUE}MCU = ${LRED}$MCU${NC}"
echo -e "${LBLUE}F_CPU = ${LRED}$F_CPU${NC}"
echo -e "${LBLUE}VARIANT = ${LRED}standard${NC}"
echo -e "${LBLUE}ARDUINO_LIBS =${NC}"
}
initializeProject()
{
read -p "Project name: " PROJECT_NAME
if [ ! -e PROJECT_NAME ]; then
mkdir $PROJECT_NAME
cd $PROJECT_NAME
makefile #Call function that makes makefile
cp -r /usr/lib/avrduino/data/include/ .
echo -e "${LGREEN}Project created successfully ${NC}"
else
echo "AVRduino: Project with name [ $PROJECT_NAME ] already exists. "
echo "AVRduino: Stop project wizard and exit."
fi
}
clear
initializeProject
. doesn't execute the script as a process, it only loads it into your current shell process.
In that context, your "shebang" line, #!/bin/bash, is just a comment.
(You can put #! doodle poodle noodle there and it will run just as well.)
When you use system, it executes in /bin/sh, and thus your bash script has syntax errors.
One way to execute scripts is to make them executable:
chmod +x /usr/lib/avrduino/script/initialize.sh
and then you can just pass it directly to system:
system("/usr/lib/avrduino/script/initialize.sh");
Or, you could explictly execute it in bash:
system("/bin/bash /usr/lib/avrduino/script/initialize.sh");
OK, here's a way one might solve your "changing directory" problem:
Rewrite initialize.sh so it takes the project name as an argument instead of asking for it interactively (that's how normal Unix tools work, so stick with it).
Then add the following to your .bashrc:
make_project()
{
/usr/lib/avrduino/script/initialize.sh "$1" && cd "$1"
}
Then you can say make_project foo and get transported to the directory "foo".
Most likely it is the misplaced shebang causing a default shell to be run - make sure the shebang is at the beginning of the first line
#!/bin/bash
# rest of script
If that does not work change your system call to
system("/bin/bash /usr/lib/avrduino/script/initialize.sh");

sos Job scheduler

i am using sos job scheduler which support many language.i accept the shell script to write jobs but i am not a shell script writer.i want to implement a following points in job scheduler:
execute a shell script A. script A return "success" if time is between 6:00AM and 3PM.else it return "fail".
on "success" execute a shell script C or on "Fail" it execute shell script B.
Script B and Script C send email with“Success” or “Failure” in subject line.
please help me to sortout the above discuss problem.
Thanks
There are two command line utilities that are helpful in this case:
date: Displays the current time/date in a specified format.
mail: Sends e-mail from the command line.
Since we only need the full hour for our logic I use the date format "+%H" (hour from 0-23). This gives the following script basis:
#!/bin/sh
hour=$(date +%H)
if [ $hour -gt 6 -a $hour -lt 15 ]; then
echo "message body" | mail -s Success <your e-mail address>
else
echo "message body" | mail -s Failure <your e-mail address>
fi
#!/bin/bash
hour=$(date +%H)
recipient="root"
case "$hour" in
[6-9]|1[0-5])
subject="success"
body="message"
;;
*)
subject="failure"
body="message"
;;
esac
echo $body | mailx -s "$subject" "$recipient"