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"
|