# === Unscramble aggregated fields ===
:disag
- s;\n([^:]+:)((.*[^\])?(\\\\)*),;\n\1\2\n\1;;
+ s;\n([^:\n]+:)(([^\n]*[^\])?(\\\\)*),;\n\1\2\n\1;;
t disag;
# === Insert FN when only N is present ===
p;' "$1"
}
+pdi_escape(){
+ local in out=''
+ for in in "$@"; do
+ out="${out}${out:+;}"
+ while [ "$in" ]; do case $in in
+ \\*) out="${out}\\\\"; in="${in#\\}" ;;
+ ,*) out="${out}\\,"; in="${in#,}" ;;
+ \;*) out="${out}\\;"; in="${in#;}" ;;
+ "$BR"*) out="${out}\\n"; in="${in#${BR}}" ;;
+ *) out="${out}${in%%[\\,;${BR}]*}"; in="${in#"${in%%[\\,;${BR}]*}"}" ;;
+ esac; done
+ done
+ printf '%s\n' "$out"
+}
+
+pdi_unescape(){
+ local in out=''
+ [ $# -gt 0 ] && in="$*" || in="$(cat)"
+ while [ "$in" ]; do case $in in
+ \\\\*) out="${out}\\"; in="${in#\\\\}" ;;
+ \\n*) out="${out}${BR}"; in="${in#\\n}" ;;
+ \\*) in="${in#\\}" ;;
+ *) out="${out}${in%%\\*}"; in="${in#"${in%%\\*}"}" ;;
+ esac; done
+ printf '%s\n' "$out"
+}
+
pdi_count(){
local card="$1" name="$2" rc='' cnt=0
while rc="${card#*${BR}${name};}"; do
}
pdi_attrib(){
- local card=":$1" name="$2" cnt="${3:-1}"
+ local card=":$1" name="$2" cnt="${3:-1}" attr="$4"
while [ $cnt -gt 0 ]; do
[ "${card#*${BR}${name};}" = "$card" ] && return 1
card="${card#*${BR}${name};}"
cnt=$((cnt - 1))
done
- printf %s\\n "${card%%:*}"
+ card="${card%%:*}"
+ if [ "$attr" ]; then
+ case $card in
+ *\;"$attr"=*) card="${card#*;${attr}=}";;
+ "$attr"=*) card="${card#${attr}=}";;
+ "$attr"|*\;"$attr"|"$attr"\;*|*\;"$attr"\;*) return 0;;
+ *) return 1;;
+ esac
+ case $card in
+ \"*\"\;*|\'*\'\;*)
+ card="${card#[\"\']}"; card="${card%%[\"\'];*}"
+ ;;
+ \"*\"|\'*\')
+ card="${card#[\"\']}"; card="${card%%[\"\']}"
+ ;;
+ *\;*) card="${card%%;*}";;
+ esac
+ fi
+ printf %s\\n "${card}"
}
pdi_value(){