135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1
 | |
| urequire DEFAULTS
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: Afficher le résultat d'une recherche par regexp et compter
 | |
| éventuellement leurs occurences
 | |
| 
 | |
| USAGE
 | |
|     $scriptname [options] [regexp]
 | |
| 
 | |
| Chaque ligne *entière* de stdin est mise en correspondance avec l'expression
 | |
| regulière qui doit avoir la syntaxe de awk. S'il y a correspondance, afficher
 | |
| soit toute l'expression matchée, soit chaque groupe s'il y a des expressions
 | |
| parenthésées, chacun des groupes étant séparé par le caractère sep.
 | |
| 
 | |
| Si l'expression régulière n'est pas spécifiée, elle vaut par défaut '.*' ce qui
 | |
| fait que toutes les lignes correspondent. Ceci peut être utile avec les options
 | |
| -s et -c.
 | |
| 
 | |
| Certaines expressions régulières sont prédéfinies. regexp peut avoir l'une des
 | |
| valeurs prédéfinies suivantes:
 | |
| 
 | |
|     ip --> "'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'"
 | |
| 
 | |
| OPTIONS
 | |
|     -F sep
 | |
|         Spécifier le caractère séparateur en sortie s'il faut afficher des
 | |
|         champs multiples. Par défaut, utiliser le caractère ':'
 | |
|         Si un séparateur vide est spécifié, le séparateur standard de awk est
 | |
|         utilisé.
 | |
|     -s  Trier le résultat
 | |
|     -C FIELDNUM
 | |
|     -c, --count
 | |
|         Compter les occurences successives de la valeur du champ FIELDNUM, et
 | |
|         afficher une ligne de la forme 'count<sep>last_line' pour chaque groupe,
 | |
|         last_line étant la dernière occurence du groupe. L'option -c correspond
 | |
|         à '-C 0', c'est à dire compter les occurences successives de toute les
 | |
|         lignes.
 | |
|         Le séparateur utilisé pour calculer le numéro de champ est sep, spécifié
 | |
|         avec l'option -F.
 | |
|     -a, --all-lines
 | |
|         Avec les options -c/-C, afficher toutes les lignes des occurences
 | |
|         successives au lieu de seulement la ligne de la dernière occurence. Ceci
 | |
|         est utile surtout avec l'option -C, pour voir les différences avec les
 | |
|         différentes lignes.
 | |
|     -m, --multiple
 | |
|         Avec les options -c/-C, n'afficher que les lignes dont le compte est
 | |
|         supérieur à 1. Avec l'option -a, les groupes contigus sont séparés par
 | |
|         une ligne '--'"
 | |
| }
 | |
| 
 | |
| function match() {
 | |
|     local regexp="$1" sep="$2"
 | |
|     awkrun ${sep:+FS="$sep"} '{
 | |
|       pos = match($0, /'"${regexp//\//\\/}"'/, out)
 | |
|       if (pos != 0) {
 | |
|         max = length(out) / 3
 | |
|         if (max == 1) {
 | |
|           print out[0]
 | |
|         } else {
 | |
|           line = ""
 | |
|           for (i = 1; i < max; i++) {
 | |
|             if (i > 1) line = line FS
 | |
|             line = line out[i]
 | |
|           }
 | |
|           print line
 | |
|         }
 | |
|       }
 | |
|     }'
 | |
| }
 | |
| function count() {
 | |
|     local field="$1" sep="$2" all_lines="$3"
 | |
|     awkrun field="$field" ${sep:+FS="$sep"} all_lines="$all_lines" '
 | |
|       BEGIN {
 | |
|         first = 1
 | |
|         lastfield = ""
 | |
|         lastline = ""
 | |
|         count = 0
 | |
|         if (all_lines == "") all_lines = 0
 | |
|         else all_lines = 1
 | |
|       }
 | |
|       !first && $field != lastfield {
 | |
|         if (!all_lines) print count FS lastline
 | |
|         count = 0
 | |
|       }
 | |
|       {
 | |
|         count = count + 1
 | |
|         lastfield = $field
 | |
|         lastline = $0
 | |
|         first = 0
 | |
|         if (all_lines) print count FS lastline
 | |
|       }
 | |
|       END {
 | |
|         print count FS lastline
 | |
|       }
 | |
|     '
 | |
| }
 | |
| 
 | |
| sep=:
 | |
| sort=
 | |
| count=
 | |
| all_lines=
 | |
| multiple=
 | |
| parse_opts "${PRETTYOPTS[@]}" \
 | |
|     --help '$exit_with display_help' \
 | |
|     -F: sep= \
 | |
|     -s sort=1 \
 | |
|     -c,--count count=0 \
 | |
|     -C: count= \
 | |
|     -a,--all-lines all_lines=1 \
 | |
|     -m,--multiple multiple=1 \
 | |
|     @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
| regexp="$1"
 | |
| [ -n "$regexp" ] || regexp=".*"
 | |
| 
 | |
| case "$regexp" in
 | |
| ip) regexp='[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+';;
 | |
| esac
 | |
| 
 | |
| cmd="$(qvals match "$regexp" "$sep")"
 | |
| [ -n "$sort" ] && cmd="$cmd | sort"
 | |
| [ -n "$count" ] && cmd="$cmd | $(qvals count "$count" "$sep" "$all_lines")"
 | |
| if [ -n "$multiple" ]; then
 | |
|     if [ -n "$all_lines" ]; then
 | |
|         cmd="$cmd | $(qvals grep -v -B 1 "^1$sep")"
 | |
|     else
 | |
|         cmd="$cmd | $(qvals grep -v "^1$sep")"
 | |
|     fi
 | |
| fi
 | |
| 
 | |
| eval "$cmd"
 |