implémenter dumpcsv --awk-map

This commit is contained in:
Jephté Clain 2017-04-02 19:09:51 +04:00
parent 42c6fa6218
commit 2fb17f7402
2 changed files with 107 additions and 11 deletions

View File

@ -1758,7 +1758,7 @@ function sortcsv() { LANG=C lsortcsv "$@"; }
################################################################################
__DUMPCSV_HELP="\
Afficher les champs spécifiés pour traitement par le shell
Afficher les champs spécifiés pour traitement par le shell ou par awk
-S, --skip-lines nblines
Sauter nblines au début du flux
@ -1785,7 +1785,7 @@ Afficher les champs spécifiés pour traitement par le shell
Spécifier le nom à utiliser pour afficher les en-têtes avec l'option -h
-n, --name NAME
Spécifier le nom à utiliser pour les options -f, -a, -b
Spécifier le nom à utiliser pour les options -f, -a, -b, -w
-f, --function
Afficher les champs comme l'appel d'une fonction, e.g:
dump value00 value01...
@ -1815,6 +1815,28 @@ Afficher les champs spécifiés pour traitement par le shell
Le nom du tableau est fixé à 'values'. L'option -n permet de spécifier le
nom de la fonction, qui vaut 'dump' par défaut. Avec -h le nom par défaut
est 'dumph'
-w, --awk-map
Afficher les champs comme une fonction awk qui permet de rechercher une
valeur et d'afficher la valeur correspondante. L'option -n permet de
spécifier le nom de la fonction, qui vaut 'mapval' par défaut.
--wtype TYPE
Spécifier le type de fonction à générer avec l'option --awk-map. Le type par
défaut est 'value'
Avec le type 'value', la fonction générée est de la forme dump(inval). Cette
fonction prend en argument la valeur de la colonne spécifiée avec --wscol,
et si cette valeur est trouvée dans les données, retourner la valeur de la
colonne spécifiée avec --wrcol
Avec le type 'array', la fonction générée est de la forme dump(inval, outvs)
Cette fonction prend en argument la valeur de la colonne spécifiée avec
--wscol, et si cette valeur est trouvée dans les données, le tableau outvs
est rempli avec les donnée de la ligne correspondante.
--wscol SFIELD
Nom du champ qui est cherché par la fonction générée avec l'option --awk-map
La valeur par défaut est '1', c'est à dire le premier champ.
--wrcol RFIELD
Nom du champ dont la valeur est retournée par la fonction générée avec
l'option '--awk-map --wtype value' en cas de correspondance.
La valeur par défaut est '2', c'est à dire le deuxième champ.
-v, --var
Affiche les champ en initialisant des variables, e.g:
names=(header0 header1)
@ -1838,6 +1860,7 @@ function ldumpcsv() {
eval "$(utools_local)"
local skip= parse_headers=1 keepf skipf show_headers
local dump=function reset=1 name hname
local wtype wscol wrcol
parse_opts "${PRETTYOPTS[@]}" \
-S:,--skip:,--skip-lines:,--skiplines: skip= \
-H,--parse-headers parse_headers=1 \
@ -1852,6 +1875,10 @@ function ldumpcsv() {
--reset reset=1 \
--no-reset reset= \
-b,--array-function dump=array-function \
-w,--awk-map dump=awk-map \
--wtype: wtype= \
--wscol: wscol= \
--wrcol: wrcol= \
-v,--var dump=var \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
@ -1876,13 +1903,64 @@ function ldumpcsv() {
case "$dump" in
function|array-function) name=dump;;
array) name=values;;
awk-map) name=mapval;;
esac
fi
case "${wtype:-value}" in
array|a) wtype=array;;
value|v) wtype=value;;
esac
[ -n "$wscol" ] || wscol=1
[ -n "$wrcol" ] || wrcol=2
local -a fields
fields=("$@")
awkcsv "${args[@]}" -v show_headers:int="$show_headers" -v hname="$hname" -v name="$name" -v dump="$dump" -v reset_values:int="$reset" -v fields[@] -e '
awkcsv "${args[@]}" -v show_headers:int="$show_headers" \
-v hname="$hname" -v name="$name" -v dump="$dump" \
-v reset_values:int="$reset" -v fields[@] \
-v wtype="$wtype" -v wscol="$wscol" -v wrcol="$wrcol" \
-e '
function init_fields() {
if (do_once("init_fields")) {
if (fields_count == 0) {
array_copy(fields, HEADERS)
fields_count = array_len(fields)
}
}
}
function before_awkmap(name, wtype) {
if (do_once("before_awkmap")) {
if (wtype == "value") {
print "function " name "(inval) {"
} else if (wtype == "array") {
print "function " name "(inval, outvs) {"
}
}
}
function awkmap(inval, outval, values, count, wtype, i) {
if (wtype == "value") {
print "if (inval == " qawk(inval) ") return " qawk(outval)
} else if (wtype == "array") {
print "if (inval == " qawk(inval) ") {"
print "delete outvs"
for (i = 1; i <= count; i++) {
print "outvs[" i "] = " qawk(values[i])
}
print "return 1"
print "}"
}
}
function after_awkmap() {
if (do_once("after_awkmap")) {
if (wtype == "value") {
print "return \"\""
} else if (wtype == "array") {
print "return 0"
}
print "}"
}
}
function dump_values(name, values, dump) {
if (dump == "function") {
print qarr(values, name)
@ -1899,12 +1977,8 @@ function dump_values(name, values, dump) {
}
}
}
function init_fields() {
if (do_once("init_fields")) {
if (fields_count == 0) {
array_copy(fields, HEADERS)
fields_count = array_len(fields)
}
function before_dump() {
if (do_once("before_dump")) {
if (show_headers) {
dump_values(hname, fields, dump == "var"? "array": dump)
}
@ -1922,10 +1996,26 @@ function init_fields() {
values[i] = get(fields[i])
i++
}
if (dump == "awk-map") {
before_awkmap(name, wtype)
if (wscol ~ /^[0-9]+$/) inval = geti(wscol)
else inval = get(wscol)
if (wrcol ~ /^[0-9]+$/) outval = geti(wrcol)
else outval = get(wrcol)
awkmap(inval, outval, values, fields_count, wtype)
} else {
before_dump()
dump_values(name, values, dump)
}
}
END {
init_fields()
if (dump == "awk-map") {
before_awkmap(name, wtype)
after_awkmap()
} else {
before_dump()
}
}' -a ''
}

View File

@ -1780,6 +1780,12 @@ function unquote_html(s) {
gsub(/&amp;/, "\\&", s)
return s
}
function qawk(s) {
gsub(/\\/, "\\\\", s)
gsub(/"/, "\\\"", s)
gsub(/\n/, "\\n", s)
return "\"" s "\""
}
function qval(s) {'"
gsub(/'/, \"'\\\\''\", s)
return \"'\" s \"'\"