in vi, how to search and append something? - regex

I have a bash file
#!/bin/bash
curl '/entry/point.json?name=ab'
echo 1
sleep 60
curl '/entry/point.json?name=bc'
echo 2
sleep 60
and so on.
I'd like to append
|jsonpp
after each curl command. How am I supposed to do that in VI? Such as
:%s/curl/?????/g

1. :global
:g/curl/norm A|jsonpp
would be my favourite
2. 'interactive' repeats:
'Highlight' curl (using * or #)
A|jsonppEsc
repeat at leisure: n. n. n. ...
3. bash functions
Alternatively,
#!/bin/bash
function curl()
{
/usr/bin/curl "$#" | jsonpp
}
curl '/entry/point.json?name=ab'
echo 1
sleep 60
curl '/entry/point.json?name=bc'
echo 2
sleep 60

:%s/^\(curl .*\)$/\1 | jsonpp/g

Related

Creating an alert function in Bash

I wanted to create a function in bash similar to a default alias I got in Ubuntu, looking like:
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
This creates a simple notification after a command has been issued with it.
For example, using
history | grep vim; sleep 5; alert
gives a notification after the sleep is done, simply saying
history | grep vim; sleep 5;
I would like to write the alert into a bash function instead, which have given some trouble with the regex.
I have tried:
function alert2 () {
ICON=$([ $? = 0 ] && echo terminal || echo error)
MSG=$(history | tail -n1 | sed -e s/^\s*[0-9]\+\s*//\;s/[\;\&\|]\s*alert$//)
notify-send --urgency=low -i $ICON $MSG
}
which would output both the linenumber in history when called itself, and give an Invalid number of options when called such as the first example.
Is this possible, and if so, how? Is it simply my regex that is faulty?
I'm running on WSL, so don't have notify-send installed:
function alert2 () {
ICON=$([ $? = 0 ] && echo terminal || echo error);
MSG=$(history | tail -n1| sed -e 's/^\s*[0-9]\+\s*//;s/[;&|]\s*alert2$//');
echo $ICON $MSG;
}
jadams#Temp046317:~/code/data-extract$ cat /etc/apt/sources.list > /dev/null ; alert2
terminal cat /etc/apt/sources.list > /dev/null
I'm hoping that this would work for you (instead of the echo):
notify-send --urgency=low -i "$ICON $MSG"

How can I get the return value of `wget` from a sh script into an `int` variable

OS: Linux raspberrypi 4.19.58-v7l+ #1245 SMP Fri Jul 12 17:31:45 BST 2019 armv7l GNU/Linux
Board: Raspberry Pi 4
I have a script:
#!/bin/bash
line=$(head -n 1 /var/www/html/configuration.txt)
file=/var/www/html/4panel/url_response.txt
if [ -f "$file" ]; then
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
echo "$?"
else
echo > $file
chown pi:pi $file
fi
which I call from a C++ program using:
int val_system = 0;
val_system = system("/var/www/html/4panel/get_page.sh");
std::cout<<"System return value: "<<val_system<<std::endl;
If there is something wrong with the script, echo "$?" will output the return value of wget, but val_system will always be 0.
Does system() returns the value of echo "$?" ? In which case 0 is correct. And if that is the case how can I put the return value of wget in val_system ?
I have taken a situation in which echo "$?" always returns 8, basically I've entered an incorrect URL and:
I have tried deleting echo "$?" but val_system still returned 0;
With echo "$?" deleted I have changed the wget line to wget -q -i "$line" -O $file --timeout=2 and val_system now returns 2048.
None of my attempts bared any fruit and I have come here to seek guidance. How can I make val_system / system() return what echo "$?" returns ?
How can I get the return value of wget from the script into an int variable that's inside the C++ program that calls the script ?
The integer value system() returned contains extra information about executed command's status along with its exit code, see system() and Status Information. You need to extract exit code using WEXITSTATUS macro, like:
std::cout << "System return value: " << WEXITSTATUS(val_system) << std::endl;
If you want to echo the status and return it, you will need to save the value of $? to a variable, and exit with it explicitly.
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
status=$?
...
echo $status
...
exit $status
If you don't need to execute echo or any other command between the call to wget and the end of the script, you can rely on the script exiting with the last status (i.e the one corresponding to the call to `wget) implicitly.

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");

No Output for Python Script Executed via Cron Job

Relatively new to running cron jobs in Centos6, I can't seem to get this Python script to execute properly. I would like this script to execute and then email me the output. I have been receiving emails, but they're empty.
So far, in Crontab I've tried entering:
*/10 * * * * cd /home/local/MYCOMPANY/purrone/MyPythonScripts_Dev1 && /usr/bin/python ParserScript_CampusInsiders.py > /var/log/cron`date +\%Y-\%m-\%d-\%H:\%M:\%S`-cron.log 2>&1 ; mailx -s "Feedparser Output" my#email.com
and
*/10 * * * * /home/local/MYCOMPANY/purrone/MyPythonScripts_Dev1/ParserScript_CampusInsiders.py > /var/log/cron`date +\%Y-\%m-\%d-\%H:\%M:\%S`-cron.log 2>&1 ; mailx -s "Feedparser Output" my#email.com
I have run chmod +x on the python script to make the script executable and the Python script has #!/usr/bin/env python at the header. What am I doing wrong here?
The other problem might be that I shouldn't be using the log file? All I see at /var/log/cron when I open with cat cron is entires like this, for example (no actual output from the script):
Jul 23 13:20:01 ent-mocdvsmg01 CROND[24681]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Jul 23 13:20:01 ent-mocdvsmg01 CROND[24684]: (MYJOB\purrone) CMD (/home/local/MYCOMPANY/purrone/MyPythonScripts_Dev1/ParserScript_CampusInsiders.py > /var/log/cron`date +\%Y-\%m-\%d-\%H:\%M:\%S`-cron.log 2>&1 ; mailx -s "Feedparser Output" my#email.com)
There is nothing going into your mailx input; it expects the message on stdin. Try running it outside of crontab as a test until it sends a valid email. You could test with:
% echo hello |mailx -s test my#email.com
Note that cron can email you the output of its run. You just need to add a line to the top of crontab like:
MAILTO = you#email.com
Solution was to omit the redirect > and instead edit the Crontab thusly:
*/15 * * * * /home/local/COMPANY/malvin/SilverChalice_CampusInsiders/SilverChalice_Parser.py | tee /home/local/COMPANY/malvin/SilverChalice_CampusInsiders`date +\%Y-\%m-\%d-\%H:\%M:\%S`-cron.log | mailx -s "SilverChalice CampusInsiders" my#email.com

How to download latest version of software from same url using wget

I would like to download a latest source code of software (WRF) from some url and automate the installation process thereafter. A sample url like is given below:-
http://www2.mmm.ucar.edu/wrf/src/WRFV3.6.1.TAR.gz
In the above url, the version number may change time to time after the developer release the new version. Now I would like to download the latest available version from the main script. I tried the following:-
wget -k -l 0 "http://www2.mmm.ucar.edu/wrf/src/" -O index.html ; cat index.html | grep -o 'http:[^"]*.gz' | grep 'WRFV'
With above code, I could pull all available version of the software. The output of the above code is below:-
http://www2.mmm.ucar.edu/wrf/src/WRFV2.0.3.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV2.1.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV2.1.2.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV2.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV2.2.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV2.2.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.0.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.0.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.1.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.2.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.2.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.3.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.3.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.4.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.4.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.5.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.5.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.6.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Chem-3.6.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3-Var-do-not-use.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.0.1.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.0.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.1.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.2.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.2.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.2.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.3.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.3.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.4.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.4.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.5.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.5.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.6.1.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.6.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3.TAR.gz
http://www2.mmm.ucar.edu/wrf/src/WRFV3_OVERLAY_3.0.1.1.TAR.gz
However, I am unable to go further to filter out only later version from the link.
Usually, for processing the html-pages i recommendig some perl tools, but because this is an Directory Index output, (probably) can be done by bash tools like grep sed and such...
The following code is divided to several smaller bash functions, for easy changes
#!/bin/bash
#getdata - should output html source of the page
getdata() {
#use wget with output to stdout or curl or fetch
curl -s "http://www2.mmm.ucar.edu/wrf/src/"
#cat index.html
}
#filer_rows - get the filename and the date columns
filter_rows() {
sed -n 's:<tr><td.*href="\([^"]*\)">.*>\([0-9].*\)</td>.*</td>.*</td></tr>:\2#\1:p' | grep "${1:-.}"
}
#sort_by_date - probably don't need comment... sorts the lines by date... ;)
sort_by_date() {
while IFS=# read -r date file
do
echo "$(date --date="$date" +%s)#$file"
done | sort -gr
}
#MAIN
file=$(getdata | filter_rows WRFV | sort_by_date | head -1 | cut -d# -f2)
echo "You want download: $file"
prints
You want download: WRFV3-Chem-3.6.1.TAR.gz
What about adding a numeric sort and taking the top line:
wget -k -l 0 "http://www2.mmm.ucar.edu/wrf/src/" -O index.html ; cat index.html | grep -o 'http:[^"]*.gz' | grep 'WRFV[0-9]*[0-9]\.[0-9]' | sort -r -n | head -1