implémenter dumpcsv et nettoyer un peu le code

This commit is contained in:
Jephte CLAIN 2016-02-29 22:01:49 +04:00
parent cb0e553a4c
commit 939b5add30
3 changed files with 122 additions and 29 deletions

View File

@ -72,9 +72,12 @@ sqvals(s)
print \"mycmd\" sqvals()
L'alias qsvals(s) existe pour compatibilité
qarr(vs)
qarr(vs, prefix)
quoter les valeurs du tableau vs pour le shell, e.g:
print \"values=(\" qarr(values) \")\"
si prefix est spécifié, il est affiché suivi d'un espace, suivi des valeurs
du tableau, ce qui permet de construire une ligne de commande, e.g.:
print qarr(values, \"mycmd\")
qsubrepl(s)
quoter une valeur pour l'argument r des fonctions sub() et gsub(). Les
@ -379,13 +382,13 @@ Scripts:
'{ if (!checkvalues(FIELDS)) exit 1 }'
Ce traitement est effectué le cas échéant après le traitement --checkfields
Cette option annule l'option -z
-k, --keep KEEPFIELDS
-k, --keep-fields KEEPFIELDS
Garder les champs spécifiés. Les autres sont supprimés de la sortie.
KEEPFIELDS est une liste de champs séparés par des virgules, ou '*' pour
spécifier de garder tous les champs, ou '' pour ne garder aucun champ.
Si un champ de KEEPFIELDS n'existe pas, il est créé.
Cette option annule l'option -z
--skip SKIPFIELDS
--skip-fields SKIPFIELDS
Exclure les champs spécifiés. SKIPFIELDS est une liste de champs séparés par
des virgules.
Pour les options --keep et --skip, un script équivalent au suivant est
@ -735,13 +738,13 @@ function lawkcsv() {
}'
local -a args headers vars
local skip_lines=0 parse_headers=
local skip=0 parse_headers=
local autosep=
local sepconf=',"' colsep=',' qchar='"' echar=
local show_headers=1 reset_fields=
local fieldmap checkfields checkvalues keepfields skipfields
local fieldmap checkfields checkvalues keepf skipf
if parse_opts \
-s:,--skip-lines: skip_lines= \
-s:,--skip-lines:,--skiplines: skip= \
-h,--parse-headers parse_headers=1 \
--sepconf: '$autosep=sepconf; set@ sepconf' \
--colsep: '$autosep=indiv; set@ colsep' \
@ -756,10 +759,10 @@ function lawkcsv() {
--re: '$set@ awkscript; append_awkscript=' \
-e:,--e:,--awk-script:,--script: append_awkscript= \
-m:,--map:,--mapfields fieldmap= \
-c:,--checkfields: checkfields= \
--checkvalues: checkvalues= \
-k:,--keep:,--keepfields: keepfields= \
--skip:,--skipfields: skipfields= \
-c:,--check-fields:,--checkfields: checkfields= \
--check-values:,--checkvalues: checkvalues= \
-k:,--keep:,--keep-fields:,--keepfields: keepf= \
--skip:,--skip-fields:,--skipfields: skipf= \
--ra:,--rae: '$set@ afterscript; append_afterscript=' \
-a:,--a:,--ae:,--after-script: append_afterscript= \
@ args -- "$@"; then
@ -815,10 +818,10 @@ function lawkcsv() {
}'
reset_fields=
fi
if [ -n "$skipfields" ]; then
[ -n "$keepfields" ] || keepfields="*"
if [ -n "$skipf" ]; then
[ -n "$keepf" ] || keepf="*"
fi
if [ -n "$keepfields" ]; then
if [ -n "$keepf" ]; then
awkscript="$awkscript"'{
if (do_once("filterfields")) {
build_skipfs(fields2keep, fields2skip, SKIPFS, ADDFS)
@ -830,11 +833,11 @@ function lawkcsv() {
fi
awkrun -f \
skip_lines:int="$skip_lines" parse_headers:int="$parse_headers" \
skip_lines:int="$skip" parse_headers:int="$parse_headers" \
autosep:int="$autosep" colsep="$colsep" qchar="$qchar" echar="$echar" \
show_headers:int="$show_headers" reset_fields:int="$reset_fields" \
fields2map="$fieldmap" fields2check="$checkfields" values2check="$checkvalues" \
fields2keep="$keepfields" fields2skip="$skipfields" \
fields2keep="$keepf" fields2skip="$skipf" \
"user_headers[@]=headers" "${vars[@]}" \
"$__AWKCSV_FUNCTIONS"'
BEGIN {
@ -914,13 +917,13 @@ Scripts:
function lgrepcsv() {
local -a args vars
local skip_lines= parse_headers=
local skip= 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= \
-s:,--skip:,--skip-lines:,--skiplines: skip= \
-h,--parse-headers parse_headers=1 \
--sepconf: sepconf= \
--colsep: colsep= \
@ -966,7 +969,7 @@ function lgrepcsv() {
headers=("$@")
if [ -z "${headers[*]}" ]; then
parse_headers=1
array_from_lines headers "$(awkrun -f lskip:int="$skip_lines" 'NR <= lskip { next }
array_from_lines headers "$(awkrun -f lskip:int="$skip" 'NR <= lskip { next }
{
count = array_parsecsv(__fields, $0)
for (i = 1; i <= count; i++) {
@ -996,7 +999,7 @@ BEGIN { ec = 1 }
}
END { exit ec }"
lawkcsv ${skip_lines:+-s "$skip_lines"} ${parse_headers:+-h} \
lawkcsv ${skip:+-s "$skip"} ${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, array_len(ORIGHEADERS))}' -a "$grepscript" \
@ -1030,10 +1033,10 @@ Flux en sortie:
function lawkfsv2csv() {
local -a args headersizes
local skip_lines=0 trim_values=1 show_headers=1
local skip=0 rtrim=1 show_headers=1
if parse_opts \
-s:,--skip-lines: skip_lines= \
-r,--no-trim trim_values= \
-s:,--skip:,--skip-lines:,--skiplines: skip= \
-r,--no-trim rtrim= \
-n,--no-headers show_headers= \
--show-headers show_headers=1 \
@ args -- "$@"; then
@ -1066,7 +1069,7 @@ function lawkfsv2csv() {
shift
awkrun -f \
skip_lines:int="$skip_lines" trim_values:int="$trim_values" show_headers:int="$show_headers" \
skip_lines:int="$skip" trim_values:int="$rtrim" show_headers:int="$show_headers" \
headers[@] starts[@] sizes[@] \
"$__AWKCSV_FUNCTIONS"'
BEGIN {
@ -1609,7 +1612,7 @@ function mergecsv() { LANG=C lmergecsv "$@"; }
__SORTCSV_HELP="\
Trier un fichier csv sur la valeur d'un champ
--skip nblines
--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 des flux.
@ -1649,7 +1652,7 @@ function lsortcsv() {
local skip=0 parse_headers=auto key=1 show_headers=1
local numeric_sort= ignore_case= reverse_sort= stable_sort= unique_sort= output=
parse_opts "${PRETTYOPTS[@]}" \
--skip: skip= \
--skip:,--skip-lines:,--skiplines: skip= \
-h,--parse-headers parse_headers=1 \
--numkeys parse_headers= \
-k:,--key: key= \
@ -1742,3 +1745,81 @@ BEGIN { if (show_headers) print headerscsv }
function csortcsv() { LANG=C lsortcsv "$@"; }
function sortcsv() { LANG=C lsortcsv "$@"; }
################################################################################
__DUMPCSV_HELP="\
Afficher les champs spécifiés pour traitement par le shell
--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 cette option est spécifiée (ce qui est le cas par défaut), les champs
spécifiés peuvent être les noms effectifs des champs. Sinon, les champs ne
peuvent être que numériques.
--numkeys
Ne pas analyser la première ligne pour les noms des champs. Les champs
spécifiés ne peuvent être que numériques.
-n, --name NAME
Spécifier le nom pour les options -f, -a, etc.
-f, --function
Afficher les champs comme l'appel d'une fonction, e.g:
dump value00 value01...
dump value10 value11...
C'est la méthode d'affichage par défaut. L'option -n permet de spécifier le
nom de la fonction, qui vaut par défaut 'dump'
-a, --array
Afficher les champs comme les valeurs d'un tableau, e.g:
values=(value00 value01...)
values=(value10 value11...)
L'option -n permet de spécifier le nom du tableau, qui vaut par défaut
'values'"
: "${__DUMPCSV_DEBUG:=}"
function ldumpcsv() {
eval "$(utools_local)"
local skip= parse_headers=1
local name dump=function
parse_opts "${PRETTYOPTS[@]}" \
--skip:,--skip-lines:,--skiplines: skip= \
-h,--parse-headers parse_headers=1 \
--numkeys parse_headers= \
-n:,--name: name= \
-f,--function dump=function \
-a,--array dump=array \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
args=(${skip:+--skip-lines "$skip"})
if [ -n "$parse_headers" ]; then array_add args -h
else array_add args -n
fi
if [ -z "$name" ]; then
case "$dump" in
function) name=dump;;
array) name=values;;
esac
fi
local -a fields
fields=("$@")
awkcsv "${args[@]}" -v name="$name" -v dump="$dump" -v fields[@] -a '{
array_new(values)
i = 1
while (i <= fields_count) {
values[i] = get(fields[i])
i++
}
if (dump == "function") {
print qarr(values, name)
} else if (dump == "array") {
print name "=(" qarr(values) ")"
}
}'
}
function cdumpcsv() { LANG=C ldumpcsv "$@"; }
function dumpcsv() { LANG=C ldumpcsv "$@"; }

View File

@ -1888,11 +1888,11 @@ function qvals( i, line) {
function sqvals() {
return " " qvals()
}
function qarr(values, i, count, line) {
line = ""
function qarr(values, prefix, i, count, line) {
line = prefix
count = array_len(values)
for (i = 1; i <= count; i++) {
if (i > 1) line = line " "
if (i > 1 || line != "") line = line " "
line = line qval(values[i])
}
return line

14
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
TOOLS=(awkrun awkcsv grepcsv awkfsv2csv mergecsv sortcsv)
TOOLS=(awkrun awkcsv grepcsv awkfsv2csv mergecsv sortcsv dumpcsv)
if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then
# créer les liens
scriptname="$(basename "$0")"
@ -122,8 +122,20 @@ $__SORTCSV_HELP"
"${prefix}sortcsv" "$@"
elif [ "$tool" == "dumpcsv" ]; then
[ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: afficher les champs d'un fichiers CSV pour traitement par le shell
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C
}
USAGE
$scriptname [options] fields...
$__DUMPCSV_HELP"
"${prefix}dumpcsv" "$@"
elif [ -n "$scriptname" ]; then
die "$scriptname: nom d'outil invalide"
else
die "Vous devez spécifier l'outil à utiliser"
fi