Detect ip with zsh or console - console

I'm trying to do some script with zsh for detect the ip and launch a script, something like that:
( there're alot of ways to get the ip, for example I get something like this: )
ifconfig | awk '/inet / {sub(/\/.*/, "", $2); print $2}' | tail -1
The question is: How I can compare the output with some string for creating a conditional...
ifconfig | awk '/inet / {sub(/\/.*/, "", $2); print $2}' | tail -1 == 172.*
I try the '==' but this fails so hard...
Any idea how to do this?

You could try using grep.
If you are trying to look for ip that has 172 in it, the following command will work.
ifconfig | awk '/inet / {sub(//.*/, "", $2); print $2}' | tail -1 | grep 172 | wc -l
However, if you want to check if ip starts with 172, the just a little change will work just fine.
ifconfig | awk '/inet / {sub(//.*/, "", $2); print $2}' | tail -1 | grep 172.* | wc -l

The problem is that if statement with | fails so hard...
The solve is...
If u assign a variable with the result of the grep with -q u can compare with -eq to true or false!

Related

Get a list of unique sender(from=) domains in postfix maillog

I am currenlty trying to extract all the sender domains from maillog. I am able to do some of that with the below command but the output is not quite what I desired. What would be the best approach to retrieve a unique list of sender domain from maillog?
grep from= /var/log/maillog | awk '{print $7}' | sort | uniq -c | sort -n
output
1 from=<user#test.com>,
1 from=<apache#app1.com>,
2 from=<bounceld_5BFa-bx0p-P3tQ-67Nn#example.com>,
2 from=<bounceld_19iI-HqaS-usVU-fqe5#example.com>,
12 reject:
666 from=<>,
desired output
test.com
app1.com
example.com
See useless use of grep; if you are using Awk anyway, you don't really need grep at all.
awk '$7 ~ /from=.*#/{split($7, a, /#/); ++count[a[2]] }
END { for(dom in count) print count[dom], dom }' /var/log/maillog
Collecting the counts in an associative array does away with the need to call sort and uniq, too. Obviously, if you don't care about the count, don't print count[dom] at the end.
This should give you the answer:
grep from= /var/log/maillog | awk '{print $7}' | grep -Po '(?=#).{1}\K.*(?=>)' | sort -n | uniq -c
... change last items to "| sort | uniq" to remove the counts.
References:
https://www.baeldung.com/linux/bash-remove-first-characters {1}\K use
Extract email addresses from log with grep or sed -Po grep function

Unix piping in system() does not work in R

I am using the system() command to run a Bash command in R, but every time I try to pipe the results of one command into the next (using '|'), I get some error.
For example:
system('grep ^SN bam_stats.txt | cut -f 2- | sed -n 8p | awk -F "\t" '{print $2}'') returns the error: Error: unexpected '{' in "system('grep ^SN bam_stats.txt | cut -f 2- | sed -n 8p | awk -F "\t" '{", and if I try to remove awk -F "\t" '{print $2}' so that I'm left with system('grep ^SN bam_stats.txt | cut -f 2- | sed -n 8p'), I get the following:
/usr/bin/grep: 2-: No such file or directory
[1] 2
I have to keep removing parts of it till I am left with only system('grep ^SN bam_stats.txt'), AKA no pipes are left, for it to work.
Here is a sample from the file 'bam_stats.txt' from which I'm extracting information:
SN filtered sequences: 0
SN sequences: 137710356
SN is sorted: 1
SN 1st fragments: 68855178
SN last fragments: 68855178
SN reads mapped: 137642653
SN reads mapped and paired: 137602018 # paired-end technology bit set + both mates mapped
SN reads unmapped: 67703
SN percentage of properly paired reads (%): 99.8
Can someone tell me why piping is not working? Apologies if this is a stupid question. Please let me know if I should provide more information.
Thank you in advance.
I don't know R but IF Rs implementation of system() just passes it's argument to a shell then, in terms of standard Unix quoting, your example
system('grep ^SN bam_stats.txt | cut -f 2- | sed -n 8p | awk -F "\t" '{print $2}'')
contains 2 strings within quotes and a string in the middle that's outside of quotes:
Inside: grep ^SN bam_stats.txt | cut -f 2- | sed -n 8p | awk -F "\t"
Outside: {print $2}
Inside: <a null string>
because the 2 quotes in the middle around '{print $2}' are ending the first quoted string then later starting a second quoted string.
You don't need sed, grep, or cut if you're using awk anyway though so try just this:
system('awk -F"\t" "/^SN/ && (++cnt==8){print \$3}" bam_stats.txt')

Unix - Using pipe inside watch command (Count connections groupped by state)

I am trying to count the amount of connections while groupping them by their 'state'.
This command achieve that goal :
netstat -ant | awk '{ print $6}' | sort | uniq -c
which provide an output that looks like that :
4 CLOSE_WAIT
1 established)
127 ESTABLISHED
1 Foreign
2 LAST_ACK
39 LISTEN
9 TIME_WAIT
I am trying to combine my command with the watch command like that :
watch -n 1 "netstat -ant | awk '{ print $6}' | sort | uniq -c"
But, the output is just of the netstat -ant command (and not the last output of the pipe).
How can I use that complex command with watch ?
This works:
watch -n1 "netstat -ant | awk '{ print \$6}' | sort | uniq -c"
You're passing a double quoted string that happens to contain single quotes. Inside a double quoted string, $s meant as literal $s must be escaped ($6 => \$6).
When you don't escape it, watch will likely receive
"netstat -ant | awk '{ print }' | sort | uniq -c"
(as $6 is likely to be unset), which would explain the output you're getting (awk '{ print }' in a pipeline is essentially a no-op, like cat).

Count and display size of incoming stdin (count lines)

Is there a program that would result in output like "wc -l" but that would update counter on more data.
Here is what I want it for:
tail -f log/production.log | grep POST | wc -l
But wc -l should be changed for something.
tail -f log/production.log | grep --line-buffered POST | awk '{printf "\r%d", ++i} END {print ""}'
This prints the line count after every line of input. The carriage return \r makes each line number overwrite the last, so you only see the most recent one.
Use grep --line-buffered to make grep flush its output after each line rather than every 4KB. Or you can combine the grep and awk into one:
tail -f log/production.log | awk '/POST/ {printf "\r%d", ++i} END {print ""}'

Output on a single line

The following code is working as expected. But I can not format the output.
It will print something like this:
mysql
test
someDB
I want the output on a single line
mysql test someDB
I tried using sed in the script but it did not work.
#!/bin/sh
for dbName in `mysqlshow -uroot -pPassWord | awk '{print $2}'`
do
echo "$dbName" | egrep -v 'Databases|information_schema';
done
whenever you want to combine all lines of output into one you can also use xargs:
e.g.
find
.
./zxcv
./fdsa
./treww
./asdf
./ewr
becomes:
find |xargs echo
. ./zxcv ./fdsa ./treww ./asdf ./ewr
you can use tr to get your output to one line
<output from somewhere> | tr "\n" " "
To do a variation combining naumcho's and rsp's answers that will work for small numbers of results:
echo $(mysqlshow -uroot -pPassWord | awk '{print $2}' | egrep -v 'Databases|information_schema')
The newline is generated by the echo command most likely, the following should do the same without the newlines (not tested)
mysqlshow -uroot -pPassWord | awk '{print $2}' | egrep -v 'Databases|information_schema'
and has the added bonus of spawning just 1 grep instead of 3 grep processes.

Resources