Parse string with bash and extract number - regex

I've got supervisor's status output, looking like this.
frontend RUNNING pid 16652, uptime 2:11:17
nginx RUNNING pid 16651, uptime 2:11:17
redis RUNNING pid 16607, uptime 2:11:32
I need to extract nginx's PID. I've done it via grep -P command, but on remote machine grep is build without perl regular expression support.
Looks like sed or awk is exactly what I need, but I don't familiar with them.
Please help me to find a way how to do it, thanks in advance.

sed 's/.*pid \([0-9]*\).*/\1/'

Using AWK alone:
awk -F'[ ,]+' '{print $4}' inputfile

$ cat $your_output | sed -s 's/.*pid \([0-9]\+\),.*/\1/'
16652
16651
16607

Solution with awk and cut
vinko#parrot:~$ cat test
frontend RUNNING pid 16652, uptime 2:11:17
nginx RUNNING pid 16651, uptime 2:11:17
redis RUNNING pid 16607, uptime 2:11:32
vinko#parrot:~$ awk '{print $4}' test | cut -d, -f 1
16652
16651
16607
for nginx only:
vinko#parrot:~$ grep nginx test | awk '{print $4}' | cut -d, -f 1
16651

Take a look at pgrep, a variant of grep specially tailored for grepping process tabless.

assuming that the grep implementation supports the -o option, you could use two greps:
output \
| grep -o '^nginx[[:space:]]\+[[:upper:]]\+[[:space:]]\+pid [0-9]\+' \
| grep -o '[0-9]\+$'

Related

Grep next word after pattern match

I'm trying to get grep/sed out the following output: "name":"test_backup_1" from the below response
{"backups":[{"name":"test_backup_1","status":"CORRUPTED","creationTime":"2019-11-08T15:03:49.460","id":"test_backup_1"}]}
I have been trying variations of the following grep -Eo 'name:"\w+\"' but no joy.
I'm not sure if it would be easier to achieve this using grep or sed?
The way I am running this is curling a response from the server and saving it to a local variable, then echo out the variable and pipe grep/sed
example of what I am running
echo ${view_backup} | grep -Eo '"name":"\w+\"'
Referencing #sundeep answer
grep -Eo '"name":"[^"]+"'
resulted in the expected output
Make sure to transform the file to one line before grep
and pipe from your curl
echo `curl --silent https://someurl | tr -d '\n' | grep -oP "(?<=name\":\")[^\"]+"`
will return
test_backup_1
If you want more variables you can chain the -oP grep like in this example where I get some data on a danish license plate (bt419329)
curl --silent https://www.tjekbil.dk/api/v2/nummerplade/bt41932 | grep -oP -m 1 "(?<=\"RegNr\":\")[^\"]+|(?<=\"MaerkeTypeNavn\":\")[^\"]+|(?<=\"MaksimumHastighed\":)[^,]+"| tr '\n' ' '
returns
BT41932 SKODA 218

How to get only process ID in specify process name in Linux?

How to get only the process ID for a specified process name in Linux?
ps -ef|grep java
test 31372 31265 0 13:41 pts/1 00:00:00 grep java
Based on the process id I will write some logic. So how do I get only the process id for a specific process name.
Sample program:
PIDS= ps -ef|grep java
if [ -z "$PIDS" ]; then
echo "nothing"
else
mail test#domain.example
fi
You can pipe your output to awk to print just the PID. For example:
ps -ef | grep nginx | awk '{print $2}'
9439
You can use:
ps -ef | grep '[j]ava'
Or if pgrep is available then better to use:
pgrep -f java
Use this: ps -C <name> -o pid=
This command ignore grep process, and just return PID:
ps -ef | grep -v grep | grep java | awk '{print $2}'
why not just pidof ?
pidof <process_name>
it will return a list of pids matching the process name
https://linux.die.net/man/8/pidof

extract a base directory from the output of ps

I am looking to extract a basedir from the output of ps -ef | grep classpath myprog.jar
root 20925 20886 1 17:41 pts/0 00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar
java is always a sub-dir under the basedir but the install path can vary from server to server e.g.
/usr/local/myprog/java/jre/bin
/opt/test/testing/myprog/java/jre/bin
So once i have my string how do I extract everything from before java until the beginning of the path?
That is, /usr/local/myprog or /opt/test/testing/myprog/
Using sed:
$ echo "root 20925 20886 1 17:41 pts/0 00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar" | sed 's/.*\ \(.*\)\/java.*/\1/'
/opt/myprog
Using grep -P:
ps -ef | grep -oP '\S+(?=/java)'
/opt/myprog
If your grep doesn't support -P then use:
s='root 20925 20886 1 17:41 pts/0 00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar'
[[ "$s" =~ (/[^[:blank:]]+)/java ]] && echo "${BASH_REMATCH[1]}"
/opt/myprog
echo "root 20925 20886 1 17:41 pts/0 00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar" | awk '{split($8,a,"/java"); print a[1]}'
Use pgrep to find all of the Java processes instead of using ps -ef | grep .... This way, you don't have to worry about your grep command showing up as one of your items.
Instead of running ps -ef, you can use the -o option to only pull up the desired fields, and most ps commands take --no-header to eliminate the header fields. This way, your script doesn't have to worry about header lines.
Finally, I am using Shell Parameter Expansion which is sometimes way easier than using sed to change a variable:
$ ps -o pid,args --no-headers $(pgrep -f "java .* myproj.jar") | while read pid command arguments
do
directory=${command%/java*}
echo "The directory for Process ID $pid is $directory"
done
By the way, you could be running multiple commands, so I loop through the ps command.
ps axo args | awk '/classpath myprog.jar/{print substr($0, 0,index($0, "java")-1)}'
For example:
$ echo '/opt/myprog/java/jre/bin -classpath myprog.jar' \
| awk '/classpath myprog.jar/{print substr($0, 0,index($0, "java")-1)}'
/opt/myprog/
You can (and probably should) switch both of the $0's to $1's if you know for sure that your path will not contain spaces. Or add additional fields to the ps -o list using commas (as in, o pid,args) and use $2 rather than $1.
You can match the following regex:
'((\/\w+)+)\/java'
and the first captured group \1 or $1 will contain the wanted string
Demo: http://regex101.com/r/zU2vV4

egrep string case

I have to grep from a file name temp which has something like this
Process State
BE_RP:1 [PL_2_3] Running
BE_RP:2 [PL_2_4] Running
BE_RP:3 [PL_2_5] Running
BE_RP:4 [PL_2_6] Running
FE_SCTP:0 [PL_2_3] Running
FE_SCTP:1 [PL_2_4] Running
BE_NMP:0 Not Running
OAM:0 Running
I need to write a egrep statement which will return the number of process which are in running or not running state.
awk '/^OAM/ { next } /Not Running[ \t]*$/{s++} END {print s, NR-s-1}' foo.txt
Prints <running> <not running>
Running
$ grep -v 'OAM' input | grep -cP '(?<!Not) Running\s*$'
6
Not Running
$ grep -v 'OAM' input | grep -cP 'Not Running\s*$'
1
sed '{
1 d
s/^[^:]*:[0-9]*[ ]*//
s/^[^]]*]//
s/^[ ]*//
}' input_file | sort | uniq -c
grep -P '^(?!OAM:0).*Running' temp | cut -f2 | wc -l

How do I find my computer's IP address using the bash shell?

Every now and again, I need to start the Django development server, and have it viewable by other machines on my network, as described here:
http://docs.djangoproject.com/en/dev/ref/django-admin/#runserver
My machine’s IP address tends to change every now and again, so I’d like to have a little shell alias or something that spits out the manage.py command with my machine’s current IP address, maybe like this:
python manage.py runserver $(COMMAND TO FIND MY MACHINE’S IP ADDRESS GOES HERE):8000
ifconfig en0 | grep inet | grep -v inet6
Output of above is expected to be in the following form:
inet 192.168.111.1 netmask 0xffffff00 broadcast 192.168.111.255
Add an awk statement to print the second column to avoid using cut (awk is a pretty standard unix tool):
ifconfig en0 | grep inet | grep -v inet6 | awk '{print $2}'
I use the following to get the current IP when on a LAN where the first few numbers of the IP are always the same (replace 192.168.111 with your own numbers):
ifconfig | grep 192.168.111 | awk '{print $2}'
To get the ip of another machine that you know the name of, try (replace hostname and 192.168.111 with your own values):
ping -c 1 hostname | grep 192.168.11 | grep 'bytes from' | awk '{print $4}' | sed 's/://g'
You might already be aware, but running
python manage.py runserver 0.0.0.0:8000
makes your machine visible to everyone on the network.
Is there a reason you'd need to specify your IP?
Thi should work as well as other commands I've already seen:
ifconfig eth0 | grep inet | awk '{print $2}' | cut -d':' -f2
Replace eth0 with the desired interface (eth0, eth1, wlan0...)
I̶ ̶t̶h̶i̶n̶k̶ ̶y̶o̶u̶ ̶c̶a̶n̶ ̶a̶l̶s̶o̶ ̶w̶r̶i̶t̶e̶:̶
̶ ̶ ̶ ̶h̶o̶s̶t̶n̶a̶m̶e̶ ̶-̶I̶ ̶|̶ ̶c̶u̶t̶ ̶-̶d̶'̶ ̶'̶ ̶-̶f̶1̶ ̶
The best solution would be to:
ifconfig | sed -n 's/.*inet addr:\([0-9.]\+\)\s.*/\1/p'
Folks are using character counts to pull the right columns from the ip address line, but using spaces as a delim makes this more scalable to different length ip addresses...
ifconfig en1 | grep inet | grep -v inet6 | cut -d" " -f2
This is a quick and dirty way, that works under OSX
/sbin/ifconfig | grep 'inet ' | grep -v '127.0.0.1' | head -n1 | awk '{print $2}'
Basically get all interfaces with an IPV4 address, skip localhost and then get the first interface.
Also, use path to ifconfig. I have seen to many shell script brake when used from ex. cron because of PATH failure.
On Mac OS X 10.11.6 El Capitan (and probably older releases), you can print your IP with
ipconfig getifaddr <device>
where <device> is en0, en1, etc.
http://osxdaily.com/2010/11/21/find-ip-address-mac/
ifconfig is probably what you're after. You'll need to either run it through grep to filter out some of the noise though.
The following command works perfectly for me on RHEL 6.3:
ifconfig | grep -v '127.0.0.1' | sed -n 's/.*inet addr:\([0-9.]\+\)\s.*/\1/p'
Simple Command to find IP Address with default interface.
ip -o route get "8.8.8.8" 2>/dev/null | sed -e 's/^.* src \([^ ]*\) .*$/\1/'
or
ip route | grep src | awk -F 'src' '{print $NF; exit}' | awk '{print $1}'
or
ip route | sed -n 's/.* src \(.*\) metric .*/\1/p' | uniq
Tested on All Unix OS
This may not be as elegant as some of the other solutions, but it works on Linux systems and is more comforting to look at than a regex:
ifconfig eth0 | grep 'inet addr:' | awk '{print $2}' | awk -F ':' '{print $2}'
Try this (if you are an Arch user)
resolveip -s $HOSTNAME
Alternative
For getting IPv4 adress you can use:
host $(uname -n) | grep "address" | grep -v "IPv6" | head -n 1 | awk '{print $4}'
For getting IPv6 one:
host $(uname -n) | grep "IPv6 address" | head -n 1 | awk '{print $5}'
You can replace $(uname -n) with $(hostname) if you'd like.
Here a solution to find the current IP address:
route -n get default|grep interface|awk ‘{ print $2 }’|xargs ipconfig getifaddr
tested on Mac only.
This checks your default interface, and use that to retrieve your primary ip.
Helpful when you have many interfaces, and tons of virtual ip addresses:
netstat -rn | gawk '/UG/ {print $NF}' | xargs ifconfig | gawk 'match($0,/inet addr:(.*) B/,a) {print a[1]}'
Recap: if you'd like to copy/paste to command line and just get the network IP address, here's what works on Mac (on WiFi):
echo $(ifconfig en0 | grep inet | grep -v inet6 | cut -d" " -f2)
Here is assigning it to bash script variable:
LOCAL_IP=$(ifconfig en0 | grep inet | grep -v inet6 | cut -d" " -f2)
This is based on answers by Valentin Rocher and Matt Kropmton
Tested on Archlinux only:
ifconfig $(route | awk '{if($1=="default") print $NF}') | awk '{if($1=="inet") print $2}'
Get the default interface with route, get the ip address of interface with ifconfig.
Because the command syntax or output may vary, you may need to change for works on your system.
On Android Shell, I'm tried:
ifconfig eth0 | grep 'inet addr' | tr -d '^[A-Za-z]+$' | tr -s ':' | cut -d ':' -f 2
On Ubuntu( and Debian like distro)
to see your local IP address:
hostname -I | awk '{print $1}'
to see your Global IP address:
curl -4 icanhazip.com
curl ifconfig.co //this responds faster
to see all information about your(or any)IP address:
whois $(curl ifconfig.co)
assumed you have installed whois on your machine, if it's not:
sudo apt-get install whois