From 939b5add30b143b5a5ec50ad4bdb3971f7536264 Mon Sep 17 00:00:00 2001 From: Jephte CLAIN Date: Mon, 29 Feb 2016 22:01:49 +0400 Subject: [PATCH] =?UTF-8?q?impl=C3=A9menter=20dumpcsv=20et=20nettoyer=20un?= =?UTF-8?q?=20peu=20le=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ulib/awk | 131 ++++++++++++++++++++++++++++++++++++++++---------- lib/ulib/base | 6 +-- uawk | 14 +++++- 3 files changed, 122 insertions(+), 29 deletions(-) diff --git a/lib/ulib/awk b/lib/ulib/awk index e88e78c..765b5f4 100644 --- a/lib/ulib/awk +++ b/lib/ulib/awk @@ -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 "$@"; } diff --git a/lib/ulib/base b/lib/ulib/base index fc87827..f7aeef3 100644 --- a/lib/ulib/base +++ b/lib/ulib/base @@ -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 diff --git a/uawk b/uawk index 5ed1e50..960adc8 100755 --- a/uawk +++ b/uawk @@ -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