1192 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			1192 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
##@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_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.
 | 
						|
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 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 (par défaut), add, delete. 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
 | 
						|
            ;;
 | 
						|
        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 "$@")"; }
 |