Getting Mount Points using awk & grep - parsing

I am trying to get mount points and their respective paths on linux. So when I run the mount -v command I get this example output
//cifst/FSR on /mnt/share/cifst/FSR type cifs ...
//sydatsttbsq01/TheBooks statements to be parsed on /mnt/share/TheBooks type cifs ...
I am trying to parse this text to display this output
/mnt/share/cifst/FSR;//cifst/FSR
/mnt/share/TheBooks;//sydatsttbsq01/TheBooks
But the /mnt on the first row is in column 3, while on the second row is in column 5 so how do I do this to get the /mnt part
mount -v | grep mnt | awk '{ print $1'} gets me the path but how do I get the mount points.

Lots of assumptions, but this works for your sample input/output:
$ cat << EOF | awk '{print $(NF-2), $1}' OFS=\;
> //cifst/FSR on /mnt/share/cifst/FSR type cifs
> //sydatsttbsq01/TheBooks statements to be parsed on /mnt/share/TheBooks type cifs
> EOF
/mnt/share/cifst/FSR;//cifst/FSR
/mnt/share/TheBooks;//sydatsttbsq01/TheBooks
The trick is to notice that it's not column 3 and 5 you're interested in, but in each case it is column NF - 2.
In this particular case, the grep is redundant because it matches each line of input, and in general grep is (almost) always redundant with awk. If you need to add the filter, do it with awk and use:
awk '/mnt/{print $(NF-2), $1}' OFS=\;

If the fields you are interested in are #1 and the next after the first field equal to "on", and they do not contain spaces, you could try this:
mount -v | awk '{a="";for(i=2;i<=NF;i++){if(a=="on")break;a=$i};print $i";"$1}'
If we add one more hypothesis that there is only one field equal to "on", another possibility is to use gensub:
mount -v | awk '{print gensub(/^(\S+).*\<on\>\s+(\S+).*/,"\\2;\\1",1)}'
Which brings us to a sed equivalent:
mount -v | sed -r 's/^(\S+).*\<on\>\s+(\S+).*/\2;\1/'

For this particular output something like this will work; bear in mind that it will break if any of the paths with spaces that you use have the word "on" in them.
mount -v | awk 'BEGIN{FS="( on | type )"; OFS=";"} $3 ~ /cifs/ {print $2,$1}'
/mnt/share/cifst/FSR;//cifst/FSR
/mnt/share/TheBooks;//sydatsttbsq01/TheBooks statements to be parsed
P.S.: You'd be much better off if you didn't use spaces in paths, replace them with ., or _, or camelcase them ...

Related

regex start of line anchor alternative

I have "file.txt" with the following and I need to get only ip addresses that start a line.
I am using gnu utilities for windows and grep seems to be not behaving incorrectly.
Random Text Here
ABC 10.0.0.0 - 10.20.0.255
IP Ping Hostname
100.5.0.20 11ms N/S
GNU grep 2.5.4
grep -Po ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} file.txt
10.0.0.0
10.20.0.255
100.5.0.20
Correct behavior should only allow 100.5.0.20 since i specified the start line anchor.
Any other Linux command solutions?
I ended up improvising,
grep -oP "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]{1,3} " file.txt| awk "{$1=$1};1" > file.txt
This will grab the ip addresses with 2 spaces, and then remove the spaces with awk.

How to output tcpdump with grep expression to stdout / file?

I am trying to output the following tcpdump grep expression to a file :
tcpdump -vvvs 1024 -l -A tcp port 80 | grep -E 'X-Forwarded-For:' --line-buffered | awk '{print $2}
I understand it is related to the line-buffered option, that sends the output to stdin. However, if I don't use --line-buffered I don't get any output at all from my tcpdump.
How can I use grep so that it will send my output directly to stdout / file in this case ?
I am trying to output the following tcpdump grep expression to a file
Then redirect the output of the last command in the pipeline to the file:
tcpdump -vvvs 1024 -l -A tcp port 80 | grep -E 'X-Forwarded-For:' --line-buffered | awk '{print $2}' >file
I understand it is related to the line-buffered option, that sends the output to stdin.
No, that's not with --line-buffered does:
$ man grep
...
--line-buffered
Force output to be line buffered. By default, output is line
buffered when standard output is a terminal and block buffered
otherwise.
so it doesn't change where the output goes, it just changes when the data is actually written to the output descriptor if it's not a terminal. It's not a terminal in this case - it's a pipe - so, by default, it's block buffered, so if grep writes 4 lines of output, and that's less than a full buffer block (buffer blocks, in this context, are typically 4K bytes in most modern UN*Xes and on Windows, so it's likely that those 4 lines won't fill the buffer), those lines will not immediately be written by grep to the pipe, so they won't show up immediately.
--line-buffered changes that behavior, so that each line is written to the pipe as it's generated, and awk sees it sooner.
You're using -l with tcpdump, which has the same effect, at least on UN*X:
$ man tcpdump
...
-l Make stdout line buffered. Useful if you want to see the data
while capturing it. E.g.,
tcpdump -l | tee dat
or
tcpdump -l > dat & tail -f dat
Note that on Windows,``line buffered'' means ``unbuffered'', so
that WinDump will write each character individually if -l is
specified.
-U is similar to -l in its behavior, but it will cause output to
be ``packet-buffered'', so that the output is written to stdout
at the end of each packet rather than at the end of each line;
this is buffered on all platforms, including Windows.
So the pipeline, as you've written it, will cause grep to see each line that tcpdump prints as soon as tcpdump prints it, and cause awk to see each of those lines that contains "X-Forwarded-For:" as soon as grep sees it and matches it.
However, if I don't use --line-buffered I don't get any output at all from my tcpdump.
You'll see it eventually, as long as grep produces a buffer's worth of output; however, that could take a very long time. --line-buffered causes grep to write out each line as it's produced, so it shows up as soon as grep produces it, rather than the buffer is full.
How can I use grep so that it will send my output directly to stdout / file in this case ?
grep is sending its (standard) output to awk, which is presumably what you want; you're extracting the second field from grep's output and printing only that.
So you don't want grep to send its (standard) output directly to the terminal or to a file, you want it to send its output to awk and have awk send its (standard) output there. If you want the output to be printed on your terminal, your command is doing the right thing; if you want it sent to a file, redirect the standard output of awk to that file.

How can I use xargs to recursively parse email addresses out of text/html files?

I tried recursively parsing email addresses from a directory of text/html files with xargs and grep but this command keep including the path (I just want the email addresses in my resulting emails.csv file).
find . -type f | xargs grep -E -o "\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" >> ~/emails.csv
Can you explain what's wrong with my grep command? I don't need this to be sorted or unique. I want to match all occurrences of email addresses in files. I need to use xargs cause I'm parsing emails in 20 GB worth of text files.
Thanks.
When you tell grep to search in more than one file, it prepends the corresponding filename to the search result. Try the following to see the effect...
First, search in a single file:
grep local /etc/hosts
# localhost is used to configure the loopback interface
127.0.0.1 localhost
Now search in two files:
grep local /etc/hosts /dev/null
/etc/hosts:# localhost is used to configure the loopback interface
/etc/hosts:127.0.0.1 localhost
To suppress the filename in which the match was found, add the -h switch to grep like this
grep -h <something> <somewhere>

Nmap and grepping of its results

folks.i would like to do reverse dns resolution using nmap where the output will be like below
Ip address resolved name
how do i go about it using grep, thanks
This should do:
nmap 8.8.8.8 | awk '/report/ {split($NF,a,"[()]");print a[2],$5}'
8.8.8.8 google-public-dns-a.google.com
The option to do reverse name resolution in Nmap (without also doing a port scan or host discovery) is -sL. Nmap also has a machine-readable output format called Grepable output, using the -oG option.
Your question asks for a solution using grep, but extracting portions of output lines is not grep's strong suit. For this, you can use awk instead:
nmap -sL 192.0.2.0/24 -oG - | awk '/^Host/{print $2, $3}'
This will have the output in this format:
64.13.134.52 (scanme.nmap.org)
If you want to remove the parentheses, you can pipe the output through tr:
nmap -sL 192.0.2.0/24 -oG - | awk '/^Host/{print $2, $3}' | tr -d '()'

Capturing certain value from iperf result using grep

I use iperf3 version and then I get the performance result like this in terminal :
[ 4] local 10.0.1.8 port 34355 connected to 10.0.1.1 port 5201
49,49,0,0,35500
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 2.19 MBytes 18.4 Mbits/sec 0 69.3 KBytes
CPU Utilization: local/sender 2.8% (0.7%u/3.3%s), remote/receiver 1.4% (0.6%u/0.9%s)
I want to use only certain values which I will use in the bash script later. What I want is like this :
35500,18.4,2.8
As far as I know I can use grep to print bandwidth only :
./src/iperf3 -c 10.0.1.1 -d -t 1 -V | grep -Po '[0-9.]*(?= Mbits/sec)'
but is it possible to obtain "35500,18.4,2.8" using grep and how to do it?
Thank you for the answers
grep with P(Perl-regex) option allows you to include multiple regexes,
$ grep -Po '(?<=,)[0-9]+$|[0-9.]*(?= Mbits/sec)|(?<=local\/sender )[^%]*' file | paste -d, - - -
35500,18.4,2.8
So your command would be,
$ ./src/iperf3 -c 10.0.1.1 -d -t 1 -V | grep -Po '(?<=,)[0-9]+$|[0-9.]*(?= Mbits/sec)|(?<=local\/sender )[^%]*' | paste -d, - - -

Resources