how can i grep the interface names given in following output of netstat -i - bash

Hi i want grep the interfaces names as a list , am getting the table of interfaces with netstat -i and it looks like this :
thanks .

It's better to use also awk to simplify expressions:
netstat -i | awk '{print $1}' | grep -vE '(Kernel|Iface)'
In this case we are using awk to print only first column and after that we filter out words from first two lines of netstat output.
P.S. Or even shorter (thanks to #etan-reisner)
netstat -i | awk '! /(Kernel|Iface)/ {print $1}'

i got the preferred output with ifconfig -a | sed 's/[ \t].*//;/^$/d'
though netstat -i | awk '{print $1}' | grep -vE '(Kernel|Iface)' is also working , but i will prefer my solution since am writing a Qt QProcess and more arguments and programs will be not a solution . thanks :)

You can use the shell itself to test/parse the interface names as well without calling either awk or sed:
netstat -i | while read iface data; do
[ $(expr "$iface" : "Kernel\|Iface") -eq 0 ] &&
printf "%s\n" "$iface"
done
Or as a one-liner (not too long):
netstat -i | while read iface data; do [ $(expr "$iface" : "Kernel\|Iface") -eq 0 ] && printf "%s\n" "$iface"; done

Related

grep search with filename as parameter

I'm working on a shell script.
OUT=$1
here, the OUT variable is my filename.
I'm using grep search as follows:
l=`grep "$pattern " -A 15 $OUT | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
The issue is that the filename parameter I must pass is test.log.However, I have the folder structure :
test.log
test.log.001
test.log.002
I would ideally like to pass the filename as test.log and would like it to search it in all log files.I know the usual way to do is by using test.log.* in command line, but I'm facing difficulty replicating the same in shell script.
My efforts:
var-$'.*'
l=`grep "$pattern " -A 15 $OUT$var | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
However, I did not get the desired result.
Hopefully this will get you closer:
#!/bin/bash
for f in "${1}*"; do
grep "$pattern" -A15 "$f"
done | grep -w $i | awk 'END{print $8}'

if-then-else based on command output

I am using netstat command to get information on networks. I want to put a condition here on protocol fetched. If it's TCP, I need to print different columns than if it's UDP.
Below is what I am trying to do, but it doesn't work. Please suggest and advise if there is something I am doing wrong:
if [$(netstat -anputw | awk '{print $1}')=="tcp"] then
netstat -anputw | awk '{print $1,",",$4"}' >> $HOME/MyLog/connections_$HOSTNAME.csv
elif [$(netstat -anputw | awk '{print $1}')=="udp"] then
netstat -anputw | awk '{print $5,",",$7}' >> $HOME/MyLog/connections_$HOSTNAME.csv
fi
I don't know what you're trying to achieve, however I think that netstat returns a list rather than a string, therefore comparing the output against a string is pointless. You have to loop it. Try the following
#!/bin/bash
OUTPUT=$(netstat -anputw | awk '{print $1}');
for LINE in $OUTPUT
do
if [[ $LINE == "tcp" ]] ; then
echo "TCP!"
elif [[ $LINE == "udp" ]] ; then
echo "UDP!"
fi
done
Why don't you separate the two cases by not asking netstat to mix them up?
netstat -anptw # Just tcp
netstat -anpuw # Just udp
Also, in the tcp case, you don't seem to care about the -p information so you might as well not ask for it. And in the udp case, there is no data in the State column, so the PID/Program name will actually be in column 6.
Putting that together, I get:
netstat -antw | awk '{print $1","$4}' >> $HOME/MyLog/connections_$HOSTNAME.csv
netstat -anpuw | awk '{print $5","$6}' >> $HOME/MyLog/connections_$HOSTNAME.csv
I suspect that isn't quite the information you're looking for either, though. Perhaps you want to distinguish between TCP listening and non-listening connections.
Always leave a space after [ and before ] in if statement and you should put command $(netstat -anputw | awk '{print $1}' under double quotes if you are doing string comparison.
Here's the final script:
if [ "$(netstat -anputw | awk '{print $1}')" == "tcp" ]; then
netstat -anputw | awk '{print $1,",",$4"}' >> $HOME/MyLog/connections_$HOSTNAME.csv
elif [ "$(netstat -anputw | awk '{print $1}') " == "udp" ]; then
netstat -anputw | awk '{print $5,",",$7}' >> $HOME/MyLog/connections_$HOSTNAME.csv
fi

Bash output to multiple variales

I'm creating a script in Bash to change all MAC addresses of my PC. I can list all network interfaces with this:
ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo
And the output of the script is:
eth0
wlan0
Now I need to create a variable for each network interface (to use it in the future), but I don't know how, and Google didn't help me...
Answer:
readarray -t interfaces < <(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo)
echo "${interfaces[0]}" # prints eth0
echo "${interfaces[1]}" # prints wlan0
And to loop over them use for:
for curInterface in "${interfaces[#]}"; do
echo "$curInterface"
done
But there are better ways to parse data:
First of all, instead of grepping < character you can use -o flag. This will output all of the data on single lines. Then you simply need the second word without : character. This is very simple in pure bash:
interfaces=()
while read -r _ curInterface _; do
interfaces+=("${curInterface%:}")
done < <(ip -o link)
Store the output in an array:
interfaces=( $(ip link | awk '/</ { print $2 }' | awk -F: '!/lo/ {print $1}') )
You can create an array from this output, and loop through it after.
my_array=( $(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo) )
You can also this exmaple giving different alternatives redirect output to array
And I could have it simpler like this with one awk command:
readarray -t youravar < <(exec ip link | awk -F': ' '/^[0-9]+:/&&!/ lo: /{print $2}')

bash: grep only lines with certain criteria

I am trying to grep out the lines in a file where the third field matches certain criteria.
I tried using grep but had no luck in filtering out by a field in the file.
I have a file full of records like this:
12794357382;0;219;215
12795287063;0;220;215
12795432063;0;215;220
I need to grep only the lines where the third field is equal to 215 (in this case, only the third line)
Thanks a lot in advance for your help!
Put down the hammer.
$ awk -F ";" '$3 == 215 { print $0 }' <<< $'12794357382;0;219;215\n12795287063;0;220;215\n12795432063;0;215;220'
12795432063;0;215;220
grep:
grep -E "[^;]*;[^;]*;215;.*" yourFile
in this case, awk would be easier:
awk -F';' '$3==215' yourFile
A solution in pure bash for the pre-processing, still needing a grep:
while read line; do
OLF_IFS=$IFS; IFS=";"
line_array=( $line )
IFS=$OLD_IFS
test "${line_array[2]}" = 215 && echo "$line"
done < file | grep _your_pattern_
Simple egrep (=grep -E)
egrep ';215;[0-d][0-d][0-d]$' /path/to/file
or
egrep ';215;[[:digit:]]{3}$' /path/to/file
How about something like this:
cat your_file | while read line; do
if [ `echo "$line" | cut -d ";" -f 3` == "215" ]; then
# This is the line you want
fi
done
Here is the sed version to grep for lines where 3rd field is 215:
sed -n '/^[^;]*;[^;]*;215;/p' file.txt
Simplify your problem by putting the 3rd field at the beginning of the line:
cut -d ";" -f 3 file | paste -d ";" - file
then grep for the lines matching the 3rd field and remove the 3rd field at the beginning:
grep "^215;" | cut -d ";" -f 2-
and then you can grep for whatever you want. So the complete solution is:
cut -d ";" -f 3 file | paste -d ";" - file | grep "^215;" | cut -d ";" -f 2- | grep _your_pattern_
Advantage: Easy to understand; drawback: many processes.

Use each line of piped output as parameter for script

I have an application (myapp) that gives me a multiline output
result:
abc|myparam1|def
ghi|myparam2|jkl
mno|myparam3|pqr
stu|myparam4|vwx
With grep and sed I can get my parameters as below
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//'
But then want these myparamx values as paramaters of a script to be executed for each parameter.
myscript.sh myparam1
myscript.sh myparam2
etc.
Any help greatly appreciated
Please see xargs. For example:
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//' | xargs -n 1 myscript.sh
May be this can help -
myapp | awk -F"|" '{ print $2 }' | while read -r line; do /path/to/script/ "$line"; done
I like the xargs -n 1 solution from Dark Falcon, and while read is a classical tool for such kind of things, but just for completeness:
myapp | awk -F'|' '{print "myscript.sh", $2}' | bash
As a side note, speaking about extraction of 2nd field, you could use cut:
myapp | cut -d'|' -f 1 # -f 1 => second field, starting from 0

Resources