ajout de grepcsv

This commit is contained in:
Jephté Clain 2014-03-03 11:24:17 +04:00
parent 77e463f0b5
commit 42779acb55
3 changed files with 167 additions and 3 deletions

13
uawk
View File

@ -1,7 +1,7 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
ALIASES=(awkrun awkfsv2csv awkcsv mergecsv sortcsv)
ALIASES=(awkrun awkfsv2csv awkcsv grepcsv mergecsv sortcsv)
if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then
# créer les liens
scriptname="$(basename "$0")"
@ -40,6 +40,17 @@ $__AWKCSV_HELP"
"${prefix}awkcsv" "$@"
elif [ "${scriptname#l}" == "grepcsv" ]; then
[ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: wrapper autour de awk pour rechercher des lignes d'un fichier csv
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C
}
USAGE
$scriptname EXPR [inputfiles...] [-- headers...]
$__GREPCSV_HELP"
"${prefix}grepcsv" "$@"
elif [ "${scriptname#l}" == "awkfsv2csv" ]; then
[ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: wrapper autour de awk pour transformer un fichier à colonnes fixes en fichier csv
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C

View File

@ -1 +1 @@
26
27

155
ulib/awk
View File

@ -248,7 +248,7 @@ Analyse du flux en entrée:
Lire la liste des champs à partir de la première ligne non ignorée du flux.
Si la liste des champs est vide, cette option est implicitement activée.
Par contre, si une liste de champs est spécifiée et que le flux en entrée
contient un ligne d'en-têtes, il *faut* spécifier explicitement cette
contient une ligne d'en-têtes, il *faut* spécifier explicitement cette
option.
--sepconf 'CQE'
Spécifier en une seule option les caractères de séparation des colonnes (C),
@ -769,6 +769,159 @@ function awkcsv() { LANG=C lawkcsv "$@"; }
################################################################################
__GREPCSV_HELP="\
Faire une recherche dans un flux csv, et afficher uniquement les lignes qui
correspondent à l'expression.
EXPR est une expression awk, e.g. 'field == \"value1\" || field == \"value2\"'
Analyse du flux en entrée:
-s, --skip-lines nblines
Sauter nblines au début du flux
-h, --parse-headers
Lire la liste des champs à partir de la première ligne non ignorée du flux.
Si la liste des champs est vide, cette option est implicitement activée.
Par contre, si une liste de champs est spécifiée et que le flux en entrée
contient un ligne d'en-têtes, il *faut* spécifier explicitement cette
option.
--sepconf 'CQE'
Spécifier en une seule option les caractères de séparation des colonnes (C),
le caractère pour encadrer les chaines (Q) et le caractère d'échappement
(E). Pour chacun des caractères, s'il n'est pas spécifié, la valeur par
défaut est prise. CQE vaut par défaut ',\"'
--colsep C
--qchar Q
--echar E
Spécifier les caractères pour l'analyse du flux csv. Seul le premier
caractère de respectivement C, Q et E est considéré.
- C est le séparateur des colonnes, e.g \",\"
- Q est le caractère employé pour encadrer la valeur d'une colonne si elle
contient le caractère C
- E est le caractère employé pour mettre en echappement le caractère Q dans
la valeur d'une colonne. Si E est vide, le caractère Q doit être doublé.
Flux en sortie:
-n, --no-headers
Ne pas afficher les en-têtes. Par défaut, les en-têtes sont affichés.
-q, --quiet
Ne pas afficher les lignes. Indiquer seulement si des lignes ont été
trouvées.
Scripts:
-v var=value
Définir une variable pour le script awk
-e script
Instructions à exécuter pour chaque ligne en entrée. Utiliser la variante
--re pour remplacer les instructions par défaut qui sont exécutées avant les
instructions de -e
Par défaut, il n'y a pas d'instructions -e et les instructions de --re sont
de créer des variables nommées d'après les colonnes du flux csv. Il est
recommandé de ne pas modifier --re
Note d'implémentation: pour des raisons d'optimisation, le traitement
effectué sur chaque ligne n'est pas aussi complet que celui de la fonction
awkcsv(): Les tableaux ORIGFIELDS et ORIGHEADERS sont disponible; par
contre, la ligne courante est au format csv non analysé. Utiliser la
fonction copyall() pour être dans les mêmes conditions que le script awkcsv."
function lgrepcsv() {
local -a args vars
local skip_lines= parse_headers=
local sepconf= colsep= qchar= echar=
local no_headers= quiet=
local awkscript=--use-default--
local append_awkscript=
if parse_opts \
-s:,--skip-lines: skip_lines= \
-h,--parse-headers parse_headers=1 \
--sepconf: sepconf= \
--colsep: colsep= \
--qchar: qchar= \
--echar: echar= \
-n,--no-headers no_headers=1 \
--show-headers no_headers= \
-q,--quiet quiet=1 \
-v:,--var: vars \
--re: '$set@ awkscript; append_awkscript=' \
-e:,--e:,--awk-script:,--script: append_awkscript= \
@ args -- "$@"; then
set -- "${args[@]}"
else
eerror "$args"
return 1
fi
local expr="$1"; shift
local -a inputfiles tmpfiles
local inputfile
while [ $# -gt 0 -a "$1" != "--" ]; do
if [ "$1" == "-" ]; then
ac_set_tmpfile inputfile
array_add tmpfiles "$inputfile"
cat >"$inputfile"
else
inputfile="$1"
fi
array_add inputfiles "$inputfile"
shift
done
shift
if [ "${#inputfiles[*]}" -eq 0 ]; then
ac_set_tmpfile inputfile
array_add tmpfiles "$inputfile"
cat >"$inputfile"
array_add inputfiles "$inputfile"
fi
local -a headers
headers=("$@")
if [ -z "${headers[*]}" ]; then
parse_headers=1
array_from_lines headers "$(awkrun -f lskip:int="$skip_lines" 'NR <= lskip { next }
{
count = array_parsecsv(__fields, $0)
for (i = 1; i <= count; i++) {
print __fields[i]
}
exit
}' -- "${inputfiles[@]}")"
fi
if [ "$awkscript" == --use-default-- ]; then
awkscript=
for header in "${headers[@]}"; do
awkscript="$awkscript
$header = oget(\"$header\")"
done
fi
local grepscript="\
BEGIN { ec = 1 }
{
$awkscript
$append_awkscript
if ($expr) {
ec = 0
if (quiet) exit
printheaders()
print
}
}
END { exit ec }"
lawkcsv ${skip_lines:+-s "$skip_lines"} ${parse_headers:+-h} \
${sepconf:+--sepconf "$sepconf"} ${colsep:+--colsep "$colsep"} ${qchar:+--qchar "$qchar"} ${echar:+--echar "$echar"} \
${no_headers:+--no-headers} -v quiet:int=$quiet \
--re '{array_parsecsv(ORIGFIELDS, $0, length(ORIGHEADERS))}' -a "$grepscript" \
-- "${headers[@]}" -- "${inputfiles[@]}"
local r=$?
ac_clean "${tmpfiles[@]}"
return $r
}
function cgrepcsv() { LANG=C lgrepcsv "$@"; }
function grepcsv() { LANG=C lgrepcsv "$@"; }
################################################################################
__AWKFSV2CSV_HELP="\
Transformer un flux fsv (colonnes à largeurs fixes) en csv