##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # outils pour gérer des fichiers .ldif ##@cooked nocomments ##@require base ##@require awk uprovide ldif urequire base awk function def_match_attr() { local attr first script script="function fix_attr(attr) { gsub(/:+$/, \"\", attr) return attr \":\" } function norm_attr(attr) { return tolower(attr) } function match_attr(attr) { attr = tolower(attr) if (" if [ -n "$*" ]; then first=1 for attr in "$@"; do attr="${attr%%:*}" if [ -n "$first" ]; then first= else script="$script || " fi script="${script}attr == tolower(\"$attr:\") || attr == tolower(\"$attr::\")" done else script="${script}1" fi script="$script) return 1 else return 0 }" echo "$script" } function def_match_value() { local pattern first script script="function match_value(line) { sub(/^[^:]+::?[ ]+/, \"\", line) if (" if [ -n "$*" ]; then first=1 for pattern in "$@"; do pattern="${pattern//\\\\/\\\\}" if [ -n "$first" ]; then first= else script="$script || " fi script="${script}line ~ /$pattern/" done else script="${script}1" fi script="$script) return 1 else return 0 }" echo "$script" } function uncut_lines() { # reformer les lignes qui sont coupées awk ' BEGIN { inline = 0 } { if (!inline) { line = $0 inline = 1 } else { if ($0 ~ /^ /) { line = line substr($0, 2) } else { print line inline = 0 line = $0 inline = 1 } } } END { if (inline) print line } ' } function cut_lines() { # couper les lignes trop longues awk ' { if (length($0) > 78) { prefix = "" maxlen = 78 line = $0 while (length(line) > maxlen) { print prefix substr(line, 1, maxlen) line = substr(line, maxlen + 1) prefix = " " maxlen = 77 } if (line != "") print prefix line } else { print } } ' } function ensure_complete_objects() { # S'assurer que le ldif ne contient que des objets complets (éliminant ainsi # les groupes ayant seulement dn:) awk ' function dump_ldif() { if (attrs) { print ldif print "" } ldif = "" attrs = 0 } /^dn:/ { dump_ldif() ldif = $0 next } $0 != "" { ldif = ldif "\n" $0 attrs = 1 } END { dump_ldif() } ' } function delete_marked_objects() { # Supprimer les objets marqués avec --DELETE--: awk ' BEGIN { keep = 0 } function dump_ldif() { if (keep) { print ldif print "" } ldif = "" keep = 1 } /^dn:/ { dump_ldif() ldif = $0 next } /^--DELETE--:/ { keep = 0 } $0 != "" { ldif = ldif "\n" $0 } END { dump_ldif() } ' } function tl_addattr() { awk ' /^dn:/ { lastattr = "" dn = $0 next } { attr = $1 if (attr != "") { if (dn != "") { print dn print "changetype: add" dn = "" } sub(/:+$/, "", attr) } print lastattr = attr } ' } function tl_modifyattr() { local modtype="$1" awkrun modtype="$modtype" ' /^dn:/ { lastattr = "" dn = $0 next } { attr = $1 if (attr == "") { if (lastattr != "") { print "-" } } else { if (dn != "") { print dn print "changetype: modify" dn = "" } sub(/:+$/, "", attr) if (lastattr != attr) { if (lastattr != "") { print "-" } print modtype ": " attr } } print lastattr = attr } ' } function tl_deleteattr() { awk ' /^dn:/ { lastattr = "" dn = $0 next } { attr = $1 if (attr == "") { if (lastattr != "") { print "-" print } } else { if (dn != "") { print dn print "changetype: modify" dn = "" } sub(/:+$/, "", attr) if (lastattr != attr) { if (lastattr != "") { print "-" } print "delete: " attr } } lastattr = attr } ' } function tl_deleteentry() { awk ' /^dn:/ { dn = $0 print dn print "changetype: delete" print "" next } ' } function tl_touchentry() { awk ' /^dn:/ { dn = $0 print dn print "changetype: modify" print "" next } ' } function tl_keepattr() { local match_attr="$1" awk "$match_attr"' $0 == "" || match_attr($1) { print } ' } function tl_keepval() { local match_attr="$1" match_value="$2" awk "$match_attr $match_value"' match_attr($1) { if (match_value($0)) { print } next } { print } ' } function tl_excludeattr() { local match_attr="$1" awk "$match_attr"' ! match_attr($1) { print } ' } function tl_excludeval() { local match_attr="$1" match_value="$2" awk "$match_attr $match_value"' match_attr($1) { if (! match_value($0)) { print } next } { print } ' } function tl_keepvalentry() { local match_attr="$1" match_value="$2" awk "$match_attr $match_value"' function keep_maybe() { if (! keep) print "--DELETE--: yes" done = 1 } /^dn:/ { keep = 0 done = 0 } match_attr($1) { if (match_value($0)) keep = 1 } $0 == "" { keep_maybe() } { print } END { if (! done) keep_maybe() } ' } function tl_excludevalentry() { local match_attr="$1" match_value="$2" awk "$match_attr $match_value"' function keep_maybe() { if (! keep) print "--DELETE--: yes" done = 1 } /^dn:/ { keep = 1 done = 0 } match_attr($1) { if (match_value($0)) keep = 0 } $0 == "" { keep_maybe() } { print } END { if (! done) keep_maybe() } ' } function tl_replval() { local script="$1"; shift script="$script function print_values() { for (i = 0; i < count; i++) { print attr \" \" values[i] } } BEGIN { count=$#" local i value let i=0 for value in "$@"; do script="$script values[$i] = $(quoted_awk "$value")" let i=$i+1 done script="$script }"' match_attr($1) { attr = fix_attr($1) while (match_attr($1)) { if (getline <= 0) break } print_values() } { print } ' awkrun value="$value" "$script" } function tl_addval() { local attr="$1"; shift local script="$(def_match_attr "$attr") function print_values() { for (i = 0; i < count; i++) { print attr \" \" values[i] } add = 0 } BEGIN { add=0 attr=fix_attr($(quoted_awk "$attr")) count=$#" local i value let i=0 for value in "$@"; do script="$script values[$i] = $(quoted_awk "$value")" let i=$i+1 done script="$script }"' /^dn:/ { add = 1 } add && match_attr($1) { while (match_attr($1)) { print status = getline if (status == 0) { # traiter EOF de façon particulière, pour ne pas dupliquer le dernier print print_values() next } else if (status < 0) { break } } print_values() } add && $0 == "" { print_values() } { print } END { if (add) print_values() } ' awk "$script" } function tl_defval() { local attr="$1"; shift local script="$(def_match_attr "$attr") function resetp() { add = 0 found = 0 } function print_values() { for (i = 0; i < count; i++) { print attr \" \" values[i] } resetp() } BEGIN { add = 0 found = 0 attr = fix_attr($(quoted_awk "$attr")) count = $#" local i value let i=0 for value in "$@"; do script="$script values[$i] = $(quoted_awk "$value")" let i=$i+1 done script="$script }"' /^dn:/ { add = 1 } add && match_attr($1) { found = 1 } add && $0 == "" { if (!found) print_values() resetp() } { print } END { if (add && !found) print_values() } ' awk "$script" } function tl_decode() { local match_attr="$1" awkrun -f "$match_attr"' function split_base64(text, result) { result = "" while (text != "") { if (result != "") result = result "\n" result = result substr(text, 1, 64) text = substr(text, 65) } return result } /^[^:]+:: / && match_attr($1) { name = $0; sub(/::.*$/, "", name) value = $0; sub(/^[^:]+:: /, "", value) decoded_value = b64decode(value) #cmd = "echo '\''" split_base64(value) "'\'' | openssl base64 -d" #decoded_value = "" #while ((cmd | getline line) > 0) { # decoded_value = decoded_value line #} #close(cmd) print name ": " decoded_value next } { print } ' } function tl_encode() { local match_attr="$1" awkrun "$match_attr"' function quote(text) { # remplacer les quotes par le caractere echappement approprie gsub('"/'/, \"'\\\\''\""', text) return text } /^[^:]+: / && match_attr($1) { name = $0; sub(/:.*$/, "", name) value = $0; sub(/^[^:]+: /, "", value) cmd = "echo '\''" quote(value) "'\'' | openssl base64" coded_value = "" while ((cmd | getline line) > 0) { coded_value = coded_value line } close(cmd) print name ":: " coded_value next } { print } ' } function tl_format() { local args show_headers asep vsep qsep escape shell cmd begincmd endcmd localvars show_headers= asep=$'\t' vsep=';' qsep= if parse_opts \ -h,--show-headers show_headers \ -F: asep= \ -R: vsep= \ --quote: qsep= \ --escape: escape \ -e shell \ -c: cmd= \ --bc: begincmd= \ --ec: endcmd= \ -l,--local localvars=1 \ @ args -- "$@"; then set -- "${args[@]}" else eerror "$args" return 1 fi [ -n "$shell" ] && show_headers=1 local -a attrs mapattrs local attr mapattr for attr in "$@"; do splitpair "$attr" mapattr attr [ -n "$attr" ] || attr="$mapattr" attr="${attr//:/}"; array_add attrs "$attr" mapattr="${mapattr//:/}"; array_add mapattrs "$mapattr" done local match_attr="$(def_match_attr "${attrs[@]}")" awkrun -f show_headers:int="$show_headers" asep="$asep" vsep="$vsep" qsep="$qsep" escape="$escape" \ shell:int="$shell" cmd="$cmd" begincmd="$begincmd" endcmd="$endcmd" localvars:int="$localvars" \ attrs[@] mapattrs[@] ' function reset_values() { for (i = 1; i <= attrs_count; i++) { attr = norm_attr(attrs[i]) values[attr] = "" } has_values = 0 } function quote_shell(value) { gsub(/'\''/, "'\'\\\\\''", value) return "'\''" value "'\''" } function dump_headers() { line = "" if (shell) { if (localvars) { print "local attributes index" for (i = 1; i <= attrs_count; i++) { attr = norm_attr(mapattrs[i]) print "local " attr } } line = line "attributes=(" for (i = 1; i <= attrs_count; i++) { attr = norm_attr(mapattrs[i]) if (i > 1) line = line " " line = line quote_shell(attr) } line = line ")" } else { for (i = 1; i <= attrs_count; i++) { attr = mapattrs[i] if (i > 1) line = line asep line = line attr } } if (line != "") print line } function dump_cmd(atbegin, atend) { if (atbegin && begincmd != "") print begincmd if (atend && endcmd != "") print endcmd } function __should_quote(s) { if (s ~ /^[[:blank:][:cntrl:][:space:]]/) return 1 if (s ~ /[[:blank:][:cntrl:][:space:]]$/) return 1 return 0 } function dump_values(atbegin, value) { if (shell) { print "index=" nr for (i = 1; i <= attrs_count; i++) { attr = norm_attr(attrs[i]) mapattr = norm_attr(mapattrs[i]) print mapattr "=" values[attr] } if (!atbegin && cmd != "") print cmd } else { line = "" for (i = 1; i <= attrs_count; i++) { attr = norm_attr(attrs[i]) if (i > 1) line = line asep value = values[attr] if (qsep != "" && index(value, qsep) != 0) { if (escape) gsub(qsep, quote_subrepl(escape) "&", value); else gsub(qsep, "&&", value); } if (qsep != "" && (index(value, qsep) != 0 || index(value, asep) != 0 || __should_quote(value))) { line = line qsep value qsep } else { line = line value } } if (line != "") print line } nr = nr + 1 } function parse_attr(line) { sub(/::?.*$/, "", line) return line } function parse_value(line) { sub(/^[^:]+::? /, "", line) return line } '"$match_attr"' BEGIN { if (show_headers) dump_headers() reset_values() nr = -1 if (shell) dump_values(1) dump_cmd(1, 0) } $0 != "" && match_attr($1) { has_values = 1 attr = norm_attr(parse_attr($0)) value = parse_value($0) if (shell) { if (values[attr] == "") { values[attr] = quote_shell(value) } else { tmp = values[attr] if (substr(tmp, 1, 1) == "(") tmp = substr(tmp, 2, length(tmp) - 2) tmp = tmp " " quote_shell(value) values[attr] = "(" tmp ")" } } else { if (values[attr] == "") { values[attr] = value } else { values[attr] = values[attr] vsep value } } } $0 == "" { if (has_values) dump_values() reset_values() } END { if (has_values) dump_values() if (shell) dump_cmd(0, 1) } ' } function tl_formatcsv() { local args show_headers vsep qsep escape show_headers=1 vsep=';' qsep='"' escape= if parse_opts \ -h,--show-headers show_headers=1 \ -n,--no-headers show_headers= \ -R: vsep= \ --quote: qsep= \ --escape: escape \ @ args -- "$@"; then set -- "${args[@]}" else eerror "$args" return 1 fi tl_format ${show_headers:+--show-headers} -F , -R "$vsep" --quote "$qsep" --escape "$escape" "$@" } function tl_parsecsv() { local -a args headers local basedn= rdnattr= skip_lines=0 parse_headers= vsep=';' if parse_opts \ -u:,--rdnattr: rdnattr= \ -s:,--skip-lines: skip_lines= \ -h,--parse-headers parse_headers=1 \ -R: vsep= \ @ args -- "$@"; then set -- "${args[@]}" else eerror "$args" return 1 fi basedn="$1"; shift if [ -n "$basedn" ]; then [ -n "$rdnattr" ] || rdnattr=uid else [ -n "$rdnattr" ] || rdnattr=dn fi [ -n "$*" ] && headers=("$@") [ -n "${headers[*]}" ] || parse_headers=1 awkrun -f \ basedn="$basedn" rdnattr="$rdnattr" \ skip_lines:int="$skip_lines" parse_headers:int="$parse_headers" headers[@] \ vsep="$vsep" ' NR <= skip_lines { next } parse_headers { array_parsecsv(headers, $0) headers_count = array_len(headers) parse_headers = 0 next } { array_parsecsv(attrvalues, $0) rdnindex = key_index(rdnattr, headers) rdnvalue = attrvalues[rdnindex] if (basedn != "") { print "dn: " rdnattr "=" rdnvalue "," basedn } else { print "dn: " rdnvalue } for (i = 1; i <= headers_count; i++) { attr = headers[i] if (basedn == "" && attr == rdnattr) { continue # ne pas écrire deux fois le même attribut } attrvalue = attrvalues[i] split(attrvalue, values, vsep) values_count = array_len(values) for (j = 1; j <= values_count; j++) { print attr ": " values[j] } } print "" } ' } function tl_parsecsvmod() { local -a args headers local basedn= rdnattr= skip_lines=0 parse_headers= vsep=';' if parse_opts \ -u:,--rdnattr: rdnattr= \ -s:,--skip-lines: skip_lines= \ -h,--parse-headers parse_headers=1 \ -R: vsep= \ @ args -- "$@"; then set -- "${args[@]}" else eerror "$args" return 1 fi basedn="$1"; shift if [ -n "$basedn" ]; then [ -n "$rdnattr" ] || rdnattr=uid else [ -n "$rdnattr" ] || rdnattr=dn fi [ -n "$*" ] && headers=("$@") [ -n "${headers[*]}" ] || parse_headers=1 awkrun -f \ basedn="$basedn" rdnattr="$rdnattr" \ skip_lines:int="$skip_lines" parse_headers:int="$parse_headers" headers[@] \ vsep="$vsep" ' NR <= skip_lines { next } parse_headers { array_parsecsv(headers, $0) headers_count = array_len(headers) parse_headers = 0 next } { array_parsecsv(attrvalues, $0) rdnindex = key_index(rdnattr, headers) rdnvalue = attrvalues[rdnindex] # déterminer d"abord s"il faut écrire l"objet printobj = 0 for (i = 1; i <= headers_count; i++) { attr = headers[i] if (attr == rdnattr) continue attrvalue = attrvalues[i] if (attrvalue == "") continue # ok on doit ecrire le dn if (basedn != "") { print "dn: " rdnattr "=" rdnvalue "," basedn } else { print "dn: " rdnvalue } print "changetype: modify" printobj = 1 break } # maintenant, écrire l"objet le cas échéant if (printobj) { for (i = 1; i <= headers_count; i++) { attr = headers[i] if (attr == rdnattr) continue attrvalue = attrvalues[i] if (attrvalue == "") { continue } else if (attrvalue ~ /^(replace|add|delete):/) { changetype = attrvalue sub(/:.*/, "", changetype) attrvalue = substr(attrvalue, length(changetype) + 2) } else { changetype = "replace" } print changetype ": " attr split(attrvalue, values, vsep) values_count = array_len(values) for (j = 1; j <= values_count; j++) { print attr ": " values[j] } print "-" } print "" } } ' } TRANSFORM_CMD_HELP="\ Il est possible de spécifier plusieurs commandes séparées par // Les expressions régulières sont celles reconnues par awk. u, uncut Fusionner les lignes coupées. Cette action est en principe effectuée automatiquement au début, sauf avec l'option --nu c, cut Couper les lignes trop longues. Il n'est pas conseillé d'appliquer des méthodes de transformation après avoir utilisé cette action. dec, decode [ATTRS...] Décoder les valeurs des attributs mentionnés si nécessaire (c'est à dire s'ils sont encodés en base64) enc, encode [ATTRS...] Encoder en base64 les valeurs des attributs mentionnés. k, keepattr ATTRS... Garder uniquement les lignes des attributs mentionnés. Ensuite, supprimer les objets ayant uniquement la ligne dn: (en d'autres termes, keepattr sans argument supprime *tout* le flux) kv, keepval ATTR PATTERNS... Pour l'attribut attr, garder uniquement les lignes pour lesquelles les valeurs correspondent aux expressions régulières. Les autres attributs ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la ligne dn: x, excludeattr ATTRS... Supprimer les lignes des attributs mentionnés. Ensuite, supprimer les objets ayant uniquement la ligne dn: xv, excludeval ATTR PATTERNS... Pour l'attribut attr, supprimer les lignes pour lesquelles les valeurs correspondent aux expressions régulières. Les autres attributs ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la ligne dn: kve, keepvalentry ATTR PATTERNS... Pour l'attribut attr, vérifier si *au moins une* valeur correspond à l'une des expressions régulières. Si c'est le cas, garder toute l'entrée, sinon supprimer toute l'entrée. xve, excludevalentry ATTR PATTERNS... Pour l'attribut attr, vérifier si *aucune* des valeurs ne correspond à l'une des expressions régulières. Si c'est le cas, garder toute l'entrée, sinon supprimer toute l'entrée. rv, replval ATTR VALUES... Remplacer toutes les valeurs de l'attribut attr par les valeurs spécifiées. av, addval ATTR VALUES... Ajouter un nouvel attribut avec les valeurs spécifiées. Si l'attribut existe déjà, les nouvelles valeurs sont ajoutées à la fin. fv, defval ATTR VALUES... Ajouter un nouvel attribut avec les valeurs spécifiées, s'il n'existe pas déjà. Si l'attribut existe déjà, cette opération est un NOP. sed ARGS awk ARGS grep ARGS sort [ARGS] awkrun [ARGS] Traiter le flux avec respectivement les commandes sed, awk, grep, sort et awkrun. awkrun est la version 'améliorée' de awk offerte par nutools. Note: ces commandes ne tiennent pas compte de la locale: elles sont lancées avec la variable LANG=C Note: aucun argument n'est filtré, mais il ne faudrait pas utiliser les options qui provoquent la modification en place d'un fichier, comme par exemple l'option -i de sed format [OPTIONS] ATTRS... Formater le flux au format ldif en données tabulaires. Chaque attribut peut être de la forme newname:oldname pour avoir des en-têtes avec un nom différent des noms des attributs. L'effet est le même qu'avec awkcsv -m -h, --show-headers Afficher les en-têtes. Par défaut, les en-têtes ne sont pas affichés. -F ASEP Spécifier le séparateur pour les attributs. Par défaut, il s'agit du caractère de tabulation. -R VSEP Spécifier le séparateur pour les valeurs des attributs. Par défaut, il s'agit du point-virgule ';' --quote QUOTE Spécifier le caractère à employer pour encadrer une valeur si elle contient l'un des caractères ASEP ou QSEP. Par défaut, les valeurs ne sont pas encadrées. --escape ESCAPE Indiquer que le caractère QUOTE dans une chaine doit être mis en échappement avec le caractère ESCAPE. Si ESCAPE est une valeur vide, doubler le caractère QUOTE. e.g. si QUOTE='\"' et ESCAPE='\\', la valeur abc\"def est écrite ainsi: \"abc\\\"def\" Par contre, si ESCAPE='', alors la valeur est écrite ainsi: \"abc\"\"def\" -e Retourner les valeurs comme des variables shell. Les options -F et -R sont ignorées. Les attributs multivalués sont écrits sous forme de tableaux. Par exemple: attributes=('mail' 'givenName') index=0 mail='user@domain.fr' givenName=('peter' 'gabriel') -l, --local Ajouter une définition pour rendre locales les variables utilisées, e.g. avec l'exemple précédent: local attributes index local mail local givenName attributes=('mail' 'givenName') index=0 mail='user@domain.fr' givenName=('peter' 'gabriel') --bc Dans le mode -e, spécifier une commande à insérer avant le premier enregistrement. Quand cette commande est lancée, index==-1 -c Dans le mode -e, spécifier une commande à insérer après chaque enregistrement --ec Dans le mode -e, spécifier une commande à insérer après le dernier enregistrement formatcsv [OPTIONS] ATTRS... Equivalent à 'format -F , --show-headers --quote \\\"' -n, --no-headers Ne pas afficher les en-têtes. Par défaut, les en-têtes sont affichés. -R VSEP --quote QUOTE --escape ESCAPE Ces options ont la même signification que pour format parsecsv [OPTIONS] BASEDN [ATTRS...] Analyser le flux au format CSV (qui a par exemple été générée avec la commande formatcsv), et reconstruire les objets LDAP associés. En principe, BASEDN n'est pas vide, et l'option -u détermine l'attribut dont la valeur est utilisée pour nommer les objets. Le cas particulier BASEDN=='' est aussi supporté, auquel cas la valeur par défaut de rdnattr n'est plus 'uid' mais 'dn' BASEDN DN de base des objets à construire -u, --rdnattr rdnattr[=uid] Nommer les objets avec la valeur de l'attribut spécifié -s, --skip-lines nblines Sauter nblines au début du flux -h, --parse-headers Lire la liste des attributs à partir de la première ligne non ignorée du flux. Si la liste des attributs est vide, cette option est implicitement activée. -R VSEP Spécifier le séparateur pour les valeurs des attributs. Par défaut, il s'agit du point-virgule ';' parsecsvmod [OPTIONS] BASEDN [ATTRS...] Analyser le flux au format CSV qui contient des ordres de modification des objets LDAP, et construire les modifications au format LDIF. L'attribut rdnattr (spécifié avec l'option -u) est le seul dont la valeur doit être au format standard. Les valeurs des autres attributs doivent être de la forme [CHANGETYPE:]value où CHANGETYPE peut valoir replace, add, ou delete. CHANGETYPE vaut replace par défaut. Si une valeur est vide, elle est ignorée En principe, BASEDN n'est pas vide, et l'option -u détermine l'attribut dont la valeur est utilisée pour nommer les objets. Le cas particulier basedn=='' est aussi supporté, auquel cas la valeur par défaut de rdnattr n'est plus 'uid' mais 'dn' BASEDN DN de base des objets à construire -u, --rdnattr rdnattr[=uid] Nommer les objets avec la valeur de l'attribut spécifié -s, --skip-lines nblines Sauter nblines au début du flux -h, --parse-headers Lire la liste des attributs à partir de la première ligne non ignorée du flux. Si la liste des attributs est vide, cette option est implicitement activée. -R VSEP Spécifier le séparateur pour les valeurs des attributs. Par défaut, il s'agit du point-virgule ';' awkcsv [OPTIONS] [ATTRS...] $(sed 's/^/ /g' <<<"$__AWKCSV_HELP") mergecsv [OPTIONS] LEFT RIGHT -k FIELD $(sed 's/^/ /g' <<<"$__MERGECSV_HELP") sortcsv [OPTIONS] INPUT -k FIELD $(sed 's/^/ /g' <<<"$__SORTCSV_HELP") lsed ARGS lawk ARGS lgrep ARGS lsort [ARGS] lawkrun [ARGS] lawkcsv [OPTIONS] [ATTRS...] lmergecsv [OPTIONS] LEFT RIGHT -k FIELD lsortcsv [OPTIONS] INPUT -k FIELD Ces commandes sont comme les commandes sans le préfixe 'l', mais elles sont lancées sans LANG=C, ce qui fait qu'elle tiennent compte de la locale. En effet, les outils de coreutils utilisent les règles de la locale pour le tri et la comparaison des chaines, et par exemple, avec LANG=fr_FR.UTF-8, la locale indique que les ponctuations doivent être ignorées pour le tri, ce qui peut poser problème. csed ARGS cawk ARGS cgrep ARGS csort [ARGS] cawkrun [ARGS] cawkcsv [OPTIONS] [ATTRS...] cmergecsv [OPTIONS] LEFT RIGHT -k FIELD csortcsv [OPTIONS] INPUT -k FIELD Ces commandes existent pour compatibilité. Ces commandes sont des aliases des commandes sans le préfixe 'c', et existent pour insister sur le fait qu'elles sont lancées avec LANG=C. Les directives suivantes transforment le flux au format ldif en une suite de commandes de modifications pour ldapmodify: A, modaddattr Créer un objet de toutes pièces avec les attributs donnés et leurs valeurs a, modaddval Ajouter les valeurs spécifiée à l'attribut r, modreplval Remplacer les valeurs de l'attribut par celles spécifiées d, moddelval Supprimer les valeurs spécifiées de l'attribut D, moddelattr Supprimer l'attribut delentry Supprimer l'objet touchentry Forcer la réplication de l'objet en simulant une modification" function get_transform_cmd() { # Créer une liste de commandes bash à évaluer en fonction des arguments: une # suite de commandes séparées par // # Les variables suivantes peuvent être définies en entrée: # _T_inputfile: # Si cette variable est non vide, lire à partir du fichier $_T_inputfile # au lieu de stdin # _T_uncut_before: # faut-il fusionner automatiquement les lignes *avant* de lancer les # commandes. # _T_cut_after: # faut-il découper automatiquement les lignes *après* avoir lancé les # commandes. local -a cmds cmdparts local cmd dest first=1 xempty xdel local auto_uncut="$_T_uncut_before" local auto_cut="$_T_cut_after" last_is_cut [ -n "$_T_inputfile" ] && dest='cat "$_T_inputfile"' if [ -n "$*" ]; then cmd= while [ "$#" -gt 0 ]; do # parce qu'on peut avoir un argument vide! if [ "$1" == // ]; then [ -n "$cmd" ] && cmds=("${cmds[@]}" "$cmd") cmd= shift continue fi cmd="${cmd:+"$cmd "}$(quoted_arg "$1")" shift done [ -n "$cmd" ] && cmds=("${cmds[@]}" "$cmd") cmd= fi for cmd in "${cmds[@]}"; do eval "set -- $cmd" cmd="$1"; shift xempty= xdel= last_is_cut= case "$cmd" in u|uncut) if [ -n "$first" -a -n "$auto_uncut" ]; then # l'uncut automatique est demandé, et la première commande est # uncut: pas besoin de faire l'uncut automatique auto_uncut= fi cmdparts=(uncut_lines) ;; c|cut) cmdparts=(cut_lines) last_is_cut=1 ;; dec|decode) cmdparts=(tl_decode "$(def_match_attr "$@")");; enc|encode) cmdparts=(tl_encode "$(def_match_attr "$@")");; k|keep|keepattr) cmdparts=(tl_keepattr "$(def_match_attr dn "$@")") xempty=1 ;; K|kv|keepval) local match_attr="$(def_match_attr "$1")"; shift cmdparts=(tl_keepval "$match_attr" "$(def_match_value "$@")") xempty=1 ;; x|exclude|excludeattr) cmdparts=(tl_excludeattr "$(def_match_attr "$@")") xempty=1 ;; dv|delval|X|xv|excludeval) local match_attr="$(def_match_attr "$1")"; shift cmdparts=(tl_excludeval "$match_attr" "$(def_match_value "$@")") xempty=1 ;; xve|excludevalentry) local match_attr="$(def_match_attr "$1")"; shift cmdparts=(tl_excludevalentry "$match_attr" "$(def_match_value "$@")") xdel=1 ;; kve|keepvalentry) local match_attr="$(def_match_attr "$1")"; shift cmdparts=(tl_keepvalentry "$match_attr" "$(def_match_value "$@")") xdel=1 ;; sv|setval|rv|replval) local match_attr="$(def_match_attr "$1")"; shift cmdparts=(tl_replval "$match_attr" "$@") xempty=1 ;; av|addval) cmdparts=(tl_addval "$@") xempty=1 ;; fv|defval) cmdparts=(tl_defval "$@") xempty=1 ;; xe|xempty|excludeempty) cmdparts=(ensure_complete_objects);; sed|awk|grep|sort) cmdparts=(LANG=C "$cmd" "$@");; csed|cawk|cgrep|csort) cmdparts=(LANG=C "${cmd#c}" "$@");; lsed|lawk|lgrep|lsort) cmdparts=("${cmd#l}" "$@");; awkrun|cawkrun) cmdparts=(cawkrun "$@");; lawkrun) cmdparts=(lawkrun "$@");; awkcsv|csvawk|cawkcsv) cmdparts=(cawkcsv "$@");; lawkcsv) cmdparts=(lawkcsv "$@");; mergecsv|cmergecsv) cmdparts=(cmergecsv "$@");; lmergecsv) cmdparts=(lmergecsv "$@");; sortcsv|csortcsv) cmdparts=(csortcsv "$@");; lsortcsv) cmdparts=(lsortcsv "$@");; f|format) cmdparts=(tl_format "$@");; fcsv|formatcsv|format_csv|csv) cmdparts=(tl_formatcsv "$@");; pcsv|parsecsv|parse_csv) cmdparts=(tl_parsecsv "$@");; pcsvmod|parsecsvmod|parse_csvmod) cmdparts=(tl_parsecsvmod "$@");; A|modaddattr) cmdparts=(tl_addattr);; a|ma|modadd|modaddval) cmdparts=(tl_modifyattr add);; r|mr|modrepl|modreplval) cmdparts=(tl_modifyattr replace);; d|md|moddel|moddelval) cmdparts=(tl_modifyattr delete);; D|moddelattr) cmdparts=(tl_deleteattr);; delentry|moddelentry) cmdparts=(tl_deleteentry);; touch|touchentry|modtouchentry) cmdparts=(tl_touchentry);; litteral) cmdpars=("$@");; *) eerror "$cmd: commande inconnue. elle sera ignorée" continue ;; esac [ -n "$auto_uncut" ] && dest="${dest:+"$dest | "}"'uncut_lines' dest="${dest:+"$dest | "}$(quoted_args "${cmdparts[@]}")" [ -n "$xempty" ] && dest="${dest:+"$dest | "}"'ensure_complete_objects' [ -n "$xdel" ] && dest="${dest:+"$dest | "}"'delete_marked_objects' first= auto_uncut= done [ -n "$auto_cut" -a -z "$last_is_cut" ] && dest="${dest:+"$dest | "}"'cut_lines' echo "$dest" } function transform() { eval "$(get_transform_cmd "$@")"; }