Come posso farlo senza "awk" nello script di shell

Nov 07 2020

Voglio leggere un file di testo con alcune condizioni

111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 123"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /favicon.ico HTTP/1.1" 404 - "
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 206"
111.196.10.3 - - [20/Jan/2020:19:43:50 +0200] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 377"
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /sit-3-shine.7.gif HTTP/1.1" 404 - "
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 375"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET /sit3-shine.7.gif HTTP/1.1" 200 15811"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 375"
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET /sit3-shine.7.gif HTTP/1.1" 200 15811"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 299"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /sit3-shine.7.gif HTTP/1.1" 200 15811"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 299"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET /sit3-shine.7.gif HTTP/1.1" 200 15811"
111.196.10.2 - - [20/Jan/2020:07:00:50 +0100] "GET /favicon.ico HTTP/1.1" 404 -"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "HEAD / HTTP/1.1" 304 299"
111.196.10.3 - - [20/Jan/2020:07:00:50 +0100] "GET / HTTP/1.1" 200 302"
111.196.10.1 - - [20/Jan/2020:07:00:50 +0100] "GET /thttpd_powered_2.gif HTTP/1.1" 200 2114"

1: Voglio uno script che conti gli indirizzi IP nel file di testo e mi dia un output come questo

111.196.10.1  8
111.196.10.2  8
111.196.10.3  7

per quanto sopra, ho scritto uno script

cat file | awk '{print $1}' | sort | uniq -c | sort -nr | awk '{print $2" "$1}'

funziona correttamente ma lo voglio senza "awk"

2: il mio secondo requisito è contare l'indirizzo IP solo quando il penultimo numero della riga inizia con 2. l'output sarà

111.196.10.1  7
111.196.10.3  7
111.196.10.2  5

per questo, ho scritto una sceneggiatura

grep '^[^"]*"[^"]*" 2' file | cut -d' ' -f1 | sort | uniq -c | sort -nr | awk '{print $2" "$1}'

funziona anche correttamente, ma lo voglio senza "awk"

Risposte

2 Quasímodo Nov 07 2020 at 19:15
  1. Puoi ottenere solo la prima colonna con Cut, quindi ordinare gli IP risultanti e contarli con Uniq.

    cut -f1 -d' ' file | sort -n | uniq -c
    
  2. Se vuoi contare solo nella riga se il penultimo numero inizia con a 2, aggiungi semplicemente un Grep.

    grep -E '2[0-9]* [0-9]+"$' t | cut -f1 -d' ' | sort -n | uniq -c
    

Testato sull'input del campione.

2 RavinderSingh13 Nov 07 2020 at 18:49

Senza awk.

grep -oE '([0-9]+\.){3}[0-9]+' Input_file | sort | uniq -c


Con awk:

Potresti per favore provare a seguire, per farlo in un unico awk.

awk '
match($1,/([0-9]+\.){3}[0-9]+/){ arr[substr($0,RSTART,RLENGTH)]++
}
END{
  for(key in arr){
    print key,arr[key]
  }
}
' Input_file

OPPURE se il primo campo è solo l'indirizzo IP, non è necessario menzionare substrnell'indice dell'array che potremmo usare direttamente $1come segue.

awk '
match($1,/([0-9]+\.){3}[0-9]+/){
  arr[$1]++
}
END{
  for(key in arr){
    print key,arr[key]
  }
}
'  Input_file

Spiegazione: aggiunta di una spiegazione dettagliata per quanto sopra.

awk '                                 ##Starting awk program from here.
match($1,/([0-9]+\.){3}[0-9]+/){      ##using match function to match IP address regex in current line.
  arr[substr($0,RSTART,RLENGTH)]++    ##Create array arr which has index as sub string of matched regex from RSTART to RLENGTH.
}
END{                                  ##Starting END block of this program from here.
  for(key in arr){                    ##Traversing through arr from here.
    print key,arr[key]                ##printing key and array value here.
  }
}
' Input_file                          ##Mentioning Input_file name here.
Barmar Nov 07 2020 at 17:56

È possibile utilizzare readper leggere due campi dall'input, quindi visualizzarli in un ordine diverso.

Quindi sostituisci

awk '{print $2" "$1}'

con

while read count ip; do
    echo "$ip $count"
done