shell script for log analysis - linux

I am getting the logs in a specific format on my linux server as
id \t IP \t login-id \t login-error Code \t attempts
I want to know all possible login-error codes which a user might have encountered.
The sample file is:
123 10.12.34.234 anshul 11 1
432 10.12.34.234 ra 11 2
342 10.12.34.234 anshul 12 1
445 10.12.34.234 yahoo 3 1
and the output should be:
anshul: 11,12
I have tried:
cat aaa | sort +2 -3 | grep anshul | awk -F"\t" {' print $4'}
This would print
11
12
But I want the output in the format as anshul: 11,12
Can we store the value in some variables and display as it is required.
Also the problem with this code is it was catch all the anshul whether it anshulg or anshuln or anshulp? Any suggestion to solve this.
I have done the sorting on login just to verify if the data I am getting is correct or not, since all the unique names would be sorted to single chunk.

1) Simple solution, but you will get extra , at the end:
cat aaa | grep "anshul" | awk '{print $4}' | tr '\n' ','
output: 11,12,
2) without extra ,:
tmp=`cat aaa | grep "anshul" | awk '{print $4}' | tr '\n' ','`
echo ${tmp%?}
output: 11,12
Of course you can easily convert this to a script that takes username as a parameter and output something like "user: anshul error(s): 11,12"

#% cat t
123 10.12.34.234 anshul 11 1
432 10.12.34.234 ra 11 2
342 10.12.34.234 anshul 12 1
445 10.12.34.234 yahoo 3 1
One line Perl.
perl -ane 'BEGIN{$x='anshul';}push #{$X{#F[2]}}, $F[3];END{print "$x: ",join(",",#{$X{$x}}),"\n";}' < t
Gives:
anshul: 11,12

awk '{a[$3]=a[$3]","$4;next}END{for(i in a)print i,substr(a[i],2)}' <your_file>|grep anshul
Or you can directly use awk without a grep.
awk '{a[$3]=a[$3]","$4;next}END{print "anshul",substr(a["anshul"],2)}' <your_file>
Tested below:
> cat temp
123 10.12.34.234 anshul 11 1
432 10.12.34.234 ra 11 2
342 10.12.34.234 anshul 12 1
445 10.12.34.234 yahoo 3 1
> awk '{a[$3]=a[$3]","$4;next}END{for(i in a)print i,substr(a[i],2)}' temp
anshul 11,12
ra 11
yahoo 3
> awk '{a[$3]=a[$3]","$4;next}END{for(i in a)print i,substr(a[i],2)}' temp|grep anshul
anshul 11,12
>
> awk '{a[$3]=a[$3]","$4;next}END{print "anshul",substr(a["anshul"],2)}' temp
anshul 11,12

Related

bash Sort uniq list of numbers and strings

I would like to sort and merge list in the following format
123 ABC
1 ABC
345 BGF
3 BGF
to
124 ABC
348 BGF
Thank you.
In bash thank you
Using awk you can do this:
awk '{a[$2]+=$1} END{for (i in a) print a[i], i}' file
124 ABC
348 BGF

Linux shell command to copy text data from a file to another

file_1 contents:
aaa 111 222 333
bbb 444 555 666
ccc 777 888 999
file_2 contents:
ddd
eee
fff
how do i copy only part of the text from file_1 to file_2
so that file_2 would become:
ddd 111 222 333
eee 444 555 666
fff 777 888 999
Try with awk:
awk 'NR==FNR{a[FNR]=$2FS$3FS$4;next} {print $0, a[FNR]}' file_1 file_2
Explanation:
NR is the current input line, FNR is the number of input line in current file, you can see that by
$ awk '{print NR,FNR}' file_1 file_2
1 1
2 2
3 3
4 1
5 2
6 3
So, the condition NR==FNR is only true when reading the first file, and that's when the columns $2, $3, and $4 get saved in a[FNR]. After reading file_1, the condition NR==FNR becomes false and the block {print $0, a[FNR]} is executed, where $0 is the whole line in file_2.

Match specific column with grep command

I am having trouble matching specific column with grep command. I have a test file (test.txt) like this..
Bra001325 835 T 13 c$c$c$c$c$cccccCcc !!!!!68886676
Bra001325 836 C 8 ,,,,,.,, 68886676
Bra001325 841 A 6 ,$,.,,. BJJJJE
Bra001325 866 C 2 ,. HJ
And i want to extract all those lines which has a number 866 in the second column. When i use grep command i am getting all the lines that contains the number that number
grep "866" test.txt
Bra001325 835 T 13 c$c$c$c$c$cccccCcc !!!!!68886676
Bra001325 836 C 8 ,,,,,.,, 68886676
Bra001325 866 C 2 ,. HJ
How can i match specific column with grep command?
Try doing this :
$ awk '$2 == 866' test.txt
No need to add {print}, the default behaviour of awk is to print on a true condition.
with grep :
$ grep -P '^\S+\s+866\b' *
But awk can print filenames too & is quite more robust than grep here :
$ awk '$2 == 866{print FILENAME":"$0; nextfile}' *
In my case, the field separator is not space but comma. So I would have to add this, otherwise it won't work for me (On ubuntu 18.04.1).
awk -F ', ' '$2 == 866' test.txt

reformatting report file using linux shell commands combining multiple lines output into one

I have a file that contains the following input:
name: ted
position:11.11.11.11"
applicationKey:88
channel:45
protocol:4
total:350
name:janet
position:170.198.80.209
applicationKey:256
channel:44
protocol:4
total:1
I like the out put to look like this
tedd 11.11.11.11 88 45 4 350
janet 170.198.80.209 256 44 4 1
Can someone help with this please ?
This should work:
awk -F':' '{printf "%s %s",$2,ORS=NF?"":"\n"}END{print "\n"}' file
$ cat file
name:ted
position:11.11.11.11
applicationKey:88
channel:45
protocol:4
total:350
name:janet
position:170.198.80.209
applicationKey:256
channel:44
protocol:4
total:1
$ awk -F':' '{printf "%s %s",$2,ORS=NF?"":"\n"}END{print "\n"}' file
ted 11.11.11.11 88 45 4 350
janet 170.198.80.209 256 44 4 1

Difference between column sum in file 1 and column sum in file 2

I have this input
file 1 file 2
A 10 222 77.11 11
B 20 2222 1.215 22
C 30 22222 12.021 33
D 40 222222 145.00 44
The output I need is (11+22+33+44)- (10+20+30+40) = 110-100=10
thank you in advance for your help
Here you go:
paste file1.txt file2.txt | awk '{s1+=$5; s2+=$2} END {print s1-s2}'
Or better yet (clever of #falsetru's answer to do the summing with a single variable):
paste file1.txt file2.txt | awk '{sum+=$5-$2} END {print sum}'
If you want to work with column N in file1 and column M in file2, this might be "easier", but less efficient:
paste <(awk '{print $N}' file1) <(awk '{print $M}' file2.txt) | awk '{sum+=$2-$1} END {print sum}'
It's easier in the sense that you don't have to count the right position of the column in the second file, but less efficient because of the added extra awk sub-processes.
Using awk:
$ cat test.txt
file 1 file 2
A 10 222 77.11 11
B 20 2222 1.215 22
C 30 22222 12.021 33
D 40 222222 145.00 44
$ tail -n +2 test.txt | awk '{s += $5 - $2} END {print s}'
10

Resources