1440 lines
38 KiB
Bash
1440 lines
38 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 (tolower(lastattr) != tolower(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 (tolower(lastattr) != tolower(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_modrdn() {
|
|
local newrdn newsup keep
|
|
local suffix="$(strlower "$3")"
|
|
local dn="$(strlower "$1")"
|
|
if [ "${1%,}" != "$1" ]; then
|
|
# ignorer le suffixe éventuellement fourni
|
|
set -- "${1%,}" "$2"
|
|
elif [ -n "$suffix" -a "${dn%,$suffix}" == "$dn" ]; then
|
|
# rajouter le suffixe
|
|
set -- "$1,$3" "$2"
|
|
fi
|
|
splitfsep "$1" , newrdn newsup
|
|
case "$2" in k|keep|keepold|keepoldrdn) keep=1;; esac
|
|
awkrun newrdn:str="$newrdn" newsup:str="$newsup" keep:int="$keep" '
|
|
/^dn:/ {
|
|
actual_newrdn = newrdn
|
|
if (actual_newrdn == "") {
|
|
actual_newrdn = $2
|
|
gsub(/,.*$/, "", actual_newrdn)
|
|
}
|
|
print
|
|
print "changetype: modrdn"
|
|
print "newrdn: " actual_newrdn
|
|
if (keep) print "deleteoldrdn: 0"
|
|
else print "deleteoldrdn: 1"
|
|
if (newsup != "") print "newsuperior: " newsup
|
|
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] = $(qawk "$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($(qawk "$attr"))
|
|
count=$#"
|
|
local i value
|
|
let i=0
|
|
for value in "$@"; do
|
|
script="$script
|
|
values[$i] = $(qawk "$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($(qawk "$attr"))
|
|
count = $#"
|
|
local i value
|
|
let i=0
|
|
for value in "$@"; do
|
|
script="$script
|
|
values[$i] = $(qawk "$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_ensureval() {
|
|
local attr="$1"; shift
|
|
local script="$(def_match_attr "$attr")
|
|
BEGIN {
|
|
resetp()
|
|
attr = fix_attr($(qawk "$attr"))
|
|
ensure_count = $#"
|
|
local i value
|
|
let i=0
|
|
for value in "$@"; do
|
|
script="$script
|
|
ensure_values[$i] = $(qawk "$value")"
|
|
let i=$i+1
|
|
done
|
|
script="$script
|
|
found_count = 0
|
|
found_values[0] = 0
|
|
delete found_values
|
|
}"'
|
|
function resetp() {
|
|
ensure = 0
|
|
found = 0
|
|
}
|
|
function get_attrvalue(line) {
|
|
sub(/^[^:]+::?[ ]+/, "", line)
|
|
return line
|
|
}
|
|
function add_to_found_values(value) {
|
|
found_values[found_count] = value
|
|
found_count++
|
|
}
|
|
function in_found_values(value, i, found_value) {
|
|
if (value ~ /^{}/) {
|
|
sub(/^{}/, "", value)
|
|
for (i = 0; i < found_count; i++) {
|
|
found_value = found_values[i]
|
|
sub(/^{[0-9]+}/, "", found_value)
|
|
if (found_value == value) {
|
|
return 1
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < found_count; i++) {
|
|
if (found_values[i] == value) {
|
|
return 1
|
|
}
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
function print_ensure_values() {
|
|
for (i = 0; i < ensure_count; i++) {
|
|
value = ensure_values[i]
|
|
sub(/^{}/, "", value)
|
|
print attr " " value
|
|
}
|
|
resetp()
|
|
}
|
|
function print_missing_values( value) {
|
|
for (i = 0; i < ensure_count; i++) {
|
|
value = ensure_values[i]
|
|
if (!in_found_values(value)) {
|
|
sub(/^{}/, "", value)
|
|
print attr " " value
|
|
}
|
|
}
|
|
resetp()
|
|
}
|
|
/^dn:/ {
|
|
ensure = 1
|
|
}
|
|
ensure && match_attr($1) {
|
|
found = 1
|
|
value = get_attrvalue($0)
|
|
add_to_found_values(value)
|
|
next
|
|
}
|
|
ensure && $0 == "" {
|
|
if (found) print_missing_values()
|
|
else print_ensure_values()
|
|
}
|
|
{ print }
|
|
END {
|
|
if (ensure) {
|
|
if (found) print_missing_values()
|
|
else print_ensure_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 }
|
|
'
|
|
}
|
|
|
|
__AWK_VSEP_FUNCTIONS='
|
|
function quote_vsep(value, vsep, hvsep) {
|
|
gsub(/\\/, "\\5c", value)
|
|
if (vsep != "\\") {
|
|
hvsep = "\\" hex(ord(vsep))
|
|
gsub(quote_regexp(vsep), hvsep, value)
|
|
}
|
|
return value
|
|
}
|
|
function unquote_vsep(value, vsep, hvsep) {
|
|
if (vsep != "\\") {
|
|
hvsep = "\\" hex(ord(vsep))
|
|
gsub(quote_regexp(hvsep), vsep, value)
|
|
}
|
|
gsub(quote_regexp("\\5c"), "\\", value)
|
|
return value
|
|
}
|
|
'
|
|
|
|
function tl_format() {
|
|
local args show_headers asep vsep qsep qempty 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= \
|
|
--quote-empty qempty=::EMPTY:: \
|
|
--empty-value: qempty= \
|
|
--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" qempty="$qempty" escape="$escape" \
|
|
shell:int="$shell" cmd="$cmd" begincmd="$begincmd" endcmd="$endcmd" localvars:int="$localvars" \
|
|
attrs[@] mapattrs[@] "$__AWK_VSEP_FUNCTIONS"'
|
|
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 (value == "") value = qempty
|
|
value = quote_vsep(value, vsep)
|
|
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='"'
|
|
qempty=1
|
|
escape=
|
|
if parse_opts \
|
|
-h,--show-headers show_headers=1 \
|
|
-n,--no-headers show_headers= \
|
|
-R: vsep= \
|
|
--quote: qsep= \
|
|
--quote-empty qempty=1 \
|
|
--no-quote-empty qempty= \
|
|
--escape: escape \
|
|
@ args -- "$@"; then
|
|
set -- "${args[@]}"
|
|
else
|
|
eerror "$args"
|
|
return 1
|
|
fi
|
|
|
|
tl_format ${show_headers:+--show-headers} -F , -R "$vsep" --quote "$qsep" ${qempty:+--quote-empty} --escape "$escape" "$@"
|
|
}
|
|
|
|
function tl_parsecsv() {
|
|
local -a args headers
|
|
local basedn= rdnattr= skip_lines=0 parse_headers= vsep=';' qempty=::EMPTY::
|
|
if parse_opts \
|
|
-u:,--rdnattr: rdnattr= \
|
|
-s:,--skip-lines: skip_lines= \
|
|
-h,--parse-headers parse_headers=1 \
|
|
-R: vsep= \
|
|
--no-parse-empty qempty= \
|
|
--parse-empty qempty=::EMPTY:: \
|
|
--empty-value: qempty= \
|
|
@ 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" qempty="$qempty" "$__AWK_VSEP_FUNCTIONS"'
|
|
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 if (rdnattr != "dn") {
|
|
print "dn: " rdnattr "=" rdnvalue
|
|
} else {
|
|
print "dn: " rdnvalue
|
|
}
|
|
for (i = 1; i <= headers_count; i++) {
|
|
attr = headers[i]
|
|
if (basedn == "" && rdnattr == "dn" && 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++) {
|
|
value = unquote_vsep(values[j], vsep)
|
|
if (value == qempty) value = ""
|
|
print attr ": " value
|
|
}
|
|
}
|
|
print ""
|
|
}
|
|
'
|
|
}
|
|
|
|
function tl_parsecsvmod() {
|
|
local -a args headers
|
|
local basedn= rdnattr= skip_lines=0 parse_headers= vsep=';' qempty=::EMPTY::
|
|
if parse_opts \
|
|
-u:,--rdnattr: rdnattr= \
|
|
-s:,--skip-lines: skip_lines= \
|
|
-h,--parse-headers parse_headers=1 \
|
|
-R: vsep= \
|
|
--no-parse-empty qempty= \
|
|
--parse-empty qempty=::EMPTY:: \
|
|
--empty-value: qempty= \
|
|
@ 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" qempty="$qempty" "$__AWK_VSEP_FUNCTIONS"'
|
|
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++) {
|
|
value = unquote_vsep(values[j], vsep)
|
|
if (value == qempty) value = ""
|
|
print attr ": " value
|
|
}
|
|
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.
|
|
xe, xempty, excludeempty
|
|
Supprimer les objets sans attributs, qui ont uniquement une ligne dn:
|
|
k, keepattr [--no-xempty] ATTRS...
|
|
Garder uniquement les attributs mentionnés, puis supprimer les objets sans
|
|
attributs avec xempty, sauf si l'option --no-xempty est spécifiée (en
|
|
d'autres termes, keepattr sans argument supprime *tout* le flux)
|
|
kv, keepval [--no-xempty] 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 sans attributs avec xempty,
|
|
sauf si l'option --no-xempty est spécifiée
|
|
x, excludeattr [--no-xempty] ATTRS...
|
|
Supprimer les lignes des attributs mentionnés. Ensuite, supprimer les objets
|
|
sans attributs avec xempty, sauf si l'option --no-xempty est spécifiée
|
|
xv, excludeval [--no-xempty] 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 sans attributs avec xempty, sauf si
|
|
l'option --no-xempty est spécifiée.
|
|
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.
|
|
ev, ensureval ATTR VALUES...
|
|
A utiliser avec modaddval, ne garder que les valeurs que l'attribut n'a pas
|
|
déjà. Par exemple, pour s'assurer que l'attribut ATTR a les valeurs V0 et
|
|
V1, on ferait:
|
|
ensureval ATTR V0 V1 // modaddval
|
|
Certains attributs sont ordonnés. Leurs valeurs sont étiquettées avec leur
|
|
index, e.g {2}value. Si l'on ne veut pas faire de correspondance exacte,
|
|
c'est à dire tester uniquement la présence d'une valeur indépendamment de
|
|
son index, il faut utiliser la syntaxe {}value, e.g:
|
|
ensureval ATTR {}value // modaddval
|
|
S'il faut ajouter les valeurs, elle sont mentionnées sans le préfixe {}
|
|
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")
|
|
dumpcsv [OPTIONS] FIELDS...
|
|
$(sed 's/^/ /g' <<<"$__DUMPCSV_HELP")
|
|
printcsv [OPTIONS] VALUES...
|
|
$(sed 's/^/ /g' <<<"$__PRINTCSV_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
|
|
ldumpcsv [OPTIONS] FIELDS...
|
|
lprintcsv [OPTIONS] VALUES...
|
|
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
|
|
rename, modrdn NEWRDN[,NEWSUPERIOR] [keep[oldrdn]] [SUFFIX]
|
|
Déplacer/renommer l'objet. L'ancienne valeur est supprimée, à moins que
|
|
l'argument keep ne soit spécifié.
|
|
Si NEWRDN est vide, alors ',NEWSUPERIOR' doit être spécifié (remarquez la
|
|
virgule avant le nouveau supérieur), et cela signifie que l'objet a le même
|
|
RDN dans la nouvelle branche.
|
|
SUFFIX est le suffixe de la base de donnée. Le DN 'NEWRDN,NEWSUPERIOR' est
|
|
exprimé relativement à SUFFIX, sauf s'il se termine par une virgule. Par
|
|
exemple, étant donné SUFFIX='dc=domain,dc=tld', les expressions suivantes
|
|
sont équivalentes:
|
|
modrdn uid=new,ou=people <=> modrdn uid=new,ou=people,dc=domain,dc=tld
|
|
modrdn uid=new,cn=config, <=> modrdn uid=new,cn=config
|
|
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.
|
|
# _T_suffix:
|
|
# suffixe de la base de données pour les commandes qui prennent des RDN,
|
|
# e.g. modrdn
|
|
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 "}$(qvalm "$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 "$@")");;
|
|
xe|xempty|excludeempty) cmdparts=(ensure_complete_objects);;
|
|
k|keep|keepattr)
|
|
[ "$1" == --no-xempty ] && shift || xempty=1
|
|
cmdparts=(tl_keepattr "$(def_match_attr dn "$@")")
|
|
;;
|
|
K|kv|keepval)
|
|
[ "$1" == --no-xempty ] && shift || xempty=1
|
|
local match_attr="$(def_match_attr "$1")"; shift
|
|
cmdparts=(tl_keepval "$match_attr" "$(def_match_value "$@")")
|
|
;;
|
|
x|exclude|excludeattr)
|
|
[ "$1" == --no-xempty ] && shift || xempty=1
|
|
cmdparts=(tl_excludeattr "$(def_match_attr "$@")")
|
|
;;
|
|
dv|delval|X|xv|excludeval)
|
|
[ "$1" == --no-xempty ] && shift || xempty=1
|
|
local match_attr="$(def_match_attr "$1")"; shift
|
|
cmdparts=(tl_excludeval "$match_attr" "$(def_match_value "$@")")
|
|
;;
|
|
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" "$@")
|
|
;;
|
|
av|addval) cmdparts=(tl_addval "$@");;
|
|
fv|defval) cmdparts=(tl_defval "$@");;
|
|
ev|ensureval) cmdparts=(tl_ensureval "$@");;
|
|
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 "$@");;
|
|
dumpcsv|cdumpcsv) cmdparts=(cdumpcsv "$@");;
|
|
ldumpcsv) cmdparts=(ldumpcsv "$@");;
|
|
printcsv|cprintcsv) cmdparts=(cprintcsv "$@");;
|
|
lprintcsv) cmdparts=(lprintcsv "$@");;
|
|
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);;
|
|
rename|modrdn|modrename|modmodrdn) cmdparts=(tl_modrdn "$1" "$2" "${3:-$_T_suffix}");;
|
|
touch|touchentry|modtouchentry) cmdparts=(tl_touchentry);;
|
|
litteral) cmdparts=("$@");;
|
|
*)
|
|
eerror "$cmd: commande inconnue. elle sera ignorée"
|
|
continue
|
|
;;
|
|
esac
|
|
[ -n "$auto_uncut" ] && dest="${dest:+"$dest | "}"'uncut_lines'
|
|
dest="${dest:+"$dest | "}$(qvals "${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 "$@")"; }
|