2 ############################################################
4 # author: devenkong(18151155@qq.com)
6 ############################################################
8 # strfmt函数是字符串中@{}变量的expanssion。不同于${}环境变量的
9 # expanssiin的是,@{}的expanssion输出到pipeline,且可以嵌套使用,
10 # 且只输出到pipeline。与strfmt类似的函数evaln实现的是字符串的多重
11 # eval,但是eval操作时,是将${}环境变量的内容expanssion到命令行,
12 # 多次expansion的方法。这在环境变量内包含的字符串内容较长,且变量嵌套
14 # 字符串进行@{}的解析之外,还可设置eval进行${}的expanssion,
15 # 和\特殊功能屏蔽符解析,以及使用trans进行\转义符的解析。
16 # strfmt函数的命令行程序为evstrn,将strfmt字符串的三种形式以参数
18 # strfmt的常用的用途,可用于templete文件中插入一些填充的信息,
19 # 或是应用中定义格式字符串,在使用时调用strfmt,根据环境变量内容,输出
20 # 不同运行环境下的字符串内容。例如系统中不同的软件的安装路径不同,使用
21 # strfmt定义的字符串,根据软件包名称等信息,输出一个软件包的安装路径。
22 # paths.shlib中定义的格式化字符串即是这个用途。
23 ############################################################
25 ############################################################
27 # strfmt函数中的变量操作和作用域的功能特性,抽象到attr.shlib
28 # 库文件中。所以需要将代码中对应的功能进行调整。
29 # 属性的表示,以__替换::,用于体现变量的层次关系。原有代码中未将
30 # 属性的代码以一个功能模块抽象成一组函数。
31 ############################################################
34 # 打开脚本中使用alias功能,否则脚本中使用alias无效,而在命令行才有效。
35 shopt -s expand_aliases
38 # @ strfmt解析的var,添加domain。${var domain}
50 ######################
52 ######################
56 ######################
58 ######################
67 ######################
69 ######################
73 ######################
75 ######################
77 #####################################################################
79 #####################################################################
83 # @ 多行字符串的fmt,输出通常为pipe或file,输出到var,通常使用evaln。
84 # # 字符串处理中,以pipe输出,逐行处理时,以var+=或var+=( $content )保存到环境变量。
85 # # 输出到file,实际以pipe输出的重定向来实现。所以strfmt的输出,都以stdout为输出。
87 # @ 输入包括var、pipe、file。
88 # # 以var为输入,用于环境变量定义的格式化字符串。
89 # # 以pipe为输入,通常输入的字符串内容较长。可以和其它程序以pipe连接,形成字符串处理链。
90 # # 以file为输入,输入的字符串内容较长,且以文件的形式存储。
91 # @ 无论是哪种输入,都转换为str的逐行处理,所以定义一个单行处理的alias命令行。
92 # # 以参数var为输入,stdout为输出。
96 # 环境变量的expanssion使用evaln进行多重eval,
97 # 多行字符串和pipe字符串的expanssion使用strfmt。
98 # 文本文件的expansion使用tmpl调用strfmt linedata,
105 # @ eval,进行$的expanssion和\特殊字符的屏蔽
107 # @ -e,与echo中的-e参数一样,对字符串中\转义符的解析
108 # @ fmt,对字符串中&var&的内容进行插入
111 # @ evaln:字符串的evaln,变量之后的@e只对参数变量进行\转义符解析,@E对字符串中的变量进行转义符的循环解析。
112 # @ strfmt:只进行&var&变量的插入。参数为var_fmt或VAR_FMT或var[1]时,输出到$var变量,其它输出到stdout。
113 # @ STRFMT_EVALN:对于fmt字符串进行eval输出,再进行变量内容的插入。设置为N或N进行evaln,其它为eval,未定义不进行eval。
114 # @ STRFMT_TRANS:对fmt字符串进行\转义符的输出。
115 # @ strfmtset:设置eval、evaln、trans参数。
118 # syntax: evaln <var-name>
119 # fdesc: 函数将指定var中的变量expanssion。字符串中的var在字符串expanssion后与其它字符串连接,
120 # 会使var的名称字符串不同,使var在expanssion时异常。须在字符串中以${var}的格式使用。
122 # var-name: eval的字符串变量名称。如果为_FMT或_fmt的sfx,expanssion的字符串保存到不含
123 # sfx的变量中。如果变量不含sfx,在stdout输出字符串。
124 # e: 只对变量字符串进行转义符解析。该参数以vname@e的形式使用。
125 # E: 对变量及其包含的变量中的转义符进行解析。
137 if [[ "$evstrn_tmp" =~ "@" ]]; then
138 evstrn_e=${evstrn_tmp##*@}
139 evstrn_tmp=${evstrn_tmp%%@*}
142 if [[ ${evstrn_tmp} =~ "_FMT" || ${evstrn_tmp} =~ "_fmt" ]]; then
143 evstrn_vname=${evstrn_tmp%%_*}
144 declare ${evstrn_vname}="${!evstrn_tmp}"
147 evstrn_vname="$evstrn_tmp"
151 if [[ "$evstrn_e" == E ]]; then
153 elif [[ "$evstrn_e" == e ]]; then
154 declare ${evstrn_vname}="`echo -ne \"${!evstrn_vname}\"`"
160 for (( evstrn_i=0; evstrn_i < evstrn_cnt; evstrn_i++ )); do
161 eval ${evstrn_vname}="$(echo -n${evstrn_e} "\"${!evstrn_vname}\"")"
162 [[ ! "${!evstrn_vname}" =~ "\$" ]] && break
165 [[ "$evstrn_tmp" == 1 ]] && echo -n${evstrn_e} "${!evstrn_vname}"
176 # # _fmt/_FMT sfx or not.
177 # # normal var or single elem array or multi elem array.
178 # # index value specified or not.
179 # # if it is an array, output is xxx[0], or, output is xxx.
180 # the difference is array attribute.
184 # xxx_fmt/XXX_FMT ==> xxx/XXX. (equal to xxx[0]/XXX[0])
185 # @ one elem array, and index is not 0
187 # xxx[$i] ==> xxx[0].
188 # xxx_fmt ==> xxx[0].
189 # xxx_fmt[$i]/XXX_FMT[$i] ==> xxx[0]/XXX[0].
191 # xxx/xxx[@] ==> stdout.
192 # xxx_fmt[@]/XXX_FMT[@] ==> xxx[@]/XXX[@].
193 # xxx_fmt/XXX_FMT ==> xxx[@]/XXX[@]. (auto detected as xxx_fmt[@]/XXX_FMT[@])
194 # xxx[$i]/XXX[$i] ==> stdout.
195 # xxx_fmt[$i]/XXX_FMT[$i] ==> xxx[0]/XXX[0].
197 # @ three kind of output
198 # # stdio: no _fmt/_FMT sfx, not an none 0 indexed single array, or not an multi array.
199 # # xxx[0]: default output var, it's equal to xxx.
200 # # xxx[@]: only multi elem array with _fmt/_FMT sfx use this output.
204 # variable with '@' is a attr, without '@' is a env var, or use attr to use env var.
210 # fsyntax: strfmt_var_name_check <str>
211 # fdesc: check file name of variable.
213 strfmt_var_name_check
()
230 if [[ $vname =~ ^@
[{]([^\
}]*)[\
}]$
]]; then
231 vname
="${BASH_REMATCH[1]}"
236 vname
="$(attr_get_vname $vname)"
237 # TBD: define paramter variable.
239 if [[ $vname =~ @
([[:alnum
:]_
:\.
-=\
>\
[\@\
*]*) ]]; then
240 vname
="${BASH_REMATCH[1]}"
242 vname
="$(attr_get_vname $vname)"
245 # err "paramter of variable name is not valid.\n"
254 if [[ $vname =~ \
[([[:alnum
:]:.
-=>]*)\
] ]]; then
255 idxp
=${BASH_REMATCH[1]}
259 # cut _fmt/_FMT sfx, get vname.
260 if [[ $vname =~
(_fmt
)$|
(_FMT
)$
]]; then
262 eval vname
=\
${vname%${BASH_REMATCH}}
264 # default vout setting is vname, or set "-stdout".
266 eval cnt
=\
${#${vname}${sfx}[@]}
268 if [[ -z $sfx ]]; then
269 if [[ $cnt == 1 ]]; then
270 eval idx
=\
${!${vname}${sfx}[@]}
271 [[ $idxp != $idx ]] && return 0 # err "specified idx in paramter is not valid.\n"
272 if [[ $idx == 0 ]]; then
276 if [[ $cnt == 2 ]]; then
277 eval idx
=\
${!${vname}${sfx}[@]}
278 if [[ ${idx:0:1} == 0 ]]; then
286 if [[ $cnt -gt 2 ]]; then
287 eval idx
=\
${!${vname}${sfx}[@]}
291 eval idx
=\
${!${vname}${sfx}[@]}
292 idxout
="[${idx%%\ *}]"
293 [[ $idxout == "[0]" ]] && idxout
=""
294 [[ $cnt == 1 && $idxp != $idx ]] && return 0 # err "specified idx in paramter is not valid.\n"
298 # eval idx=\${!${vname}${sfx}[@]}
299 # declare -p vname idx sfx vout idxout cnt
301 [[ "$idx" =~
[^
0-9\
] ]] && opt
="-A"
305 [[ $i != 0 ]] && idxout
="$idxout"
306 if [[ $vout == '-stdout' ]]; then
307 strfmt_pipe
<<< "${!vname}"
309 # dbgoutd "$vout$idxout=\$(strfmt_pipe <<< \"@{$vname${sfx}$idx}\")\n"
310 tmp
="$(strfmt_pipe <<< "@
{$vname${sfx}$idx}")"
311 # dbgoutd "tmp=$tmp\n"
313 declare -g $opt $vout$idxout="$tmp"
322 # index number for '@' var name processing.
329 # store the dispatch result
330 ##strfmt_type= # env/func/vfunc
346 vdata
=strfmt_
${strfmt_nest}_data
347 vidx
=strfmt_
${strfmt_nest}_idx
348 vlen
=strfmt_
${strfmt_nest}_len
350 vtype
=strfmt_
${strfmt_nest}_vtype
351 vname
=strfmt_
${strfmt_nest}_vname
352 vfunc
=strfmt_
${strfmt_nest}_vfunc
353 vparam
=strfmt_
${strfmt_nest}_param
355 echo xxxxxxxxxxxxxxxxxxxxxxx
359 echo xxxxxxxxxxxxxxxxxxxxxxx
364 echo xxxxxxxxxxxxxxxxxxxxxxx
367 # matching '@' prefix, and get the variable name string len.
368 strfmt_get_var_name_str
()
383 vdata
=strfmt_
${strfmt_nest}_data
384 vidx
=strfmt_
${strfmt_nest}_idx
385 vlen
=strfmt_
${strfmt_nest}_len
387 # if no @var, string dispaly, update idx value.
388 eval tmp
="\"\${$vdata:${!vidx}}\""
389 if [[ ! ${tmp} =~ @
]]; then
391 eval ${vidx}=${!vlen}
395 vtype
=strfmt_
${strfmt_nest}_vtype
396 vname
=strfmt_
${strfmt_nest}_vname
397 vfunc
=strfmt_
${strfmt_nest}_vfunc
398 vparam
=strfmt_
${strfmt_nest}_param
403 # variable beginning matching.
405 if [[ "$tmp" =~
[^
\\]?
(@
[{\
(]?
) ]]; then
408 # it means there is a '\' before '@'
409 # update $vidx, and return for next processing.
410 if [[ -n $tmp && "${tmp: -1}" == '\' ]]; then
411 eval $vidx=$(( $vidx + ${#tmp} + 1 ))
413 # TBD: the idx value is not correct
419 # display the prevous string before @var.
421 case ${BASH_REMATCH[1]} in
423 eval $vidx=$(( $vidx + ${#tmp} + 1 ))
424 eval tmp="\"\${$vdata:${!vidx}}\""
429 if [[ "${tmp}" =~ [^\\]?@[{\(]? ]]; then
430 strfmt_get_var_name_str
435 eval $vidx=$(( $vidx + ${#tmp} + 2 ))
436 eval tmp="\"\${$vdata:${!vidx}}\""
441 eval $vidx=$(( $vidx + ${#tmp} + 2 ))
442 eval tmp="\"\${$vdata:${!vidx}}\""
445 # echo xxxxxxxxxxxxxxxx
452 # variable ending matching.
454 # eval tmp="\"\${tmp:${!vidx}}\""
455 if [[ -n $syntax && "$tmp" =~ $syntax ]]; then
456 eval tmp="\"\${tmp%%${quote}*}\""
458 eval $vidx=$(( $vidx + ${#tmp} + 1 ))
460 tmp="${tmp%%[^[:alnum:]_:.=>]*}"
461 eval $vidx=$(( $vidx + ${#tmp} ))
463 eval $vname="\"${tmp}\""
465 # no variable, string dispaly.
466 # should not be running here.
468 eval ${vidx}=${!vlen}
475 if [[ "$quote" != ')' ]]; then
477 # dbgoutd "${FCGREEN}@{${!vname}}${CNORMAL}\n"
478 attr_get ${!vname} | strfmt_pipe
482 dbgoutd "$tmp($(attr_type $tmp))\n"
484 # check executable type
485 # @() processing. recogonize cmd type.
486 case $(attr_type "$tmp") in
488 err "should not be running here.\n"
493 # echo "${FCGREEN}@{${vname} $strfmt_param}${CNORMAL}"
494 attr_func ${!vname} ${!vparam} | strfmt_pipe
498 # echo "${FCGREEN}@{${vfunc} $strfmt_param}${CNORMAL}"
499 attr_func $vfunc $strfmt_param | strfmt_pipe
502 # for unkown type, the default action is command running.
503 eval "${!vname}" | strfmt_pipe
510 # this code matching @{var} name by regex
514 if [[ "${tmp}" =~ [^\\]?@([[:alnum:]_:.=>]*) ]]; then
515 # if [[ "${tmp}" =~ '@\
(([^\
}]*)\
)' ]]; then
516 eval $vidx=$(( $vidx + ${#BASH_REMATCH} ))
517 # eval $vlen=${#BASH_REMATCH}
518 eval $vname="${BASH_REMATCH:1}"
519 elif [[ "${tmp}" =~ [^\\]?@\{([^}]*)\} ]]; then
521 eval $vidx=$(( $vidx + ${#tmp} ))
522 # $vlen=$(( ${#BASH_REMATCH} + 3 ))
524 elif [[ "${tmp}" =~ [^\\]?@\(([^\)]*)\) ]]; then
526 eval $vidx=$(( $vidx + ${#tmp} ))
527 # $vlen=$(( ${#BASH_REMATCH} + 3 ))
530 eval $vidx=$(( $vidx + ${#tmp} ))
536 # fsyntax: strfmt_pipe
538 # $1格式解析后输出到$2。不指定第二个参数时,或第二个参数为-时,输出到stdout
555 # dbgoutd "strfmt_nest=$strfmt_nest\n"
556 vlen=strfmt_${strfmt_nest}_len
557 vidx=strfmt_${strfmt_nest}_idx
558 vdata=strfmt_${strfmt_nest}_data
560 vtype=strfmt_${strfmt_nest}_vtype
561 vname=strfmt_${strfmt_nest}_vname
562 vfunc=strfmt_${strfmt_nest}_vfunc
563 vparam=strfmt_${strfmt_nest}_param
572 declare -g $vparam=""
575 # set IFS paramter, or, the previous blanks in a line can not be readed.
578 while read -r $vdata; do
579 # when blank line readed.
580 [[ -z ${!vdata} ]] && echo && continue;
582 eval declare -g $vlen="\${#${vdata}}"
585 # newline char appending begin from the second line data in a variable.
586 if [[ $flag != 0 ]]; then
592 # get @{var} in string, and output variable content.
593 while [[ ${!vidx} -lt ${!vlen} ]]; do
594 strfmt_get_var_name_str
603 # fsyntax: strfmt <str-var>
604 # fdesc: output the formated string in paramter $1. all variable used in the string
605 # should be initialized. if those variables defined in a attr var, invoke attr_domain()
606 # to set the domain first.
611 # dbgoutd "strfmt $1\n"
614 if [[ $# != 0 ]]; then
615 if [[ $# == 1 && ${1} =~ ([[:alnum:]_]*)(_evl|_EVL)$ ]]; then
616 if [[ ${1:0:1} == '@
' || "$1" =~ :: ]]; then
617 attr_declare ${BASH_REMATCH[1]}="$(echo "${1}")"
619 declare -g ${BASH_REMATCH[1]}="$(echo "${1}")"
622 strfmt_var_name_check $1
623 [[ $? == 0 ]] && return
625 # XXX: it seems can not running to here.
628 # if [[ $# == 1 && ${1} =~ (_fmt)$|(_FMT)$ ]]; then
630 # strfmt_pipe <<< "$@"
632 elif [[ "$(readlink /proc/self/fd/0)" =~ 'pipe
:[' ]]; then
640 # fsyntax: strfmt_set_domain <domain-str>
641 # fdesc: 设置作用域。作用域字符串以imi和section名称组合。
647 [[ -z $imi ]] && STRFMT_DOMAIN="" && return
650 STRFMT_DOMAIN="${imi}__${section}_"
651 # echo "strfmt_set_domain($STRFMT_DOMAIN)"
655 # fsyntax: strfmtset <str-var>
656 # fdesc: 设置eval、evaln、trans参数。
659 if [[ "$2" =~ "en" ]]; then
671 elif [[ "$2" =~ "dis" ]]; then
688 # fsyntax: strtrunc <str> <char>
689 # fdesc: 设置作用域。作用域字符串以imi和section名称组合。
692 [[ -z ${!1} || -z $2 ]] && return
694 if [[ "${!1}" =~ ^([^$2]*)$2(.*) ]]; then
695 eval ${1}[1]="\${BASH_REMATCH[1]}"
696 eval ${1}[2]="\${BASH_REMATCH[2]}"
701 # fsyntax: strsplit <str> <left_bracket> <right_bracket>
702 # fdesc: 设置作用域。作用域字符串以imi和section名称组合。
705 [[ -z ${!1} || -z $2 ]] && return
707 if eval [[ "${STR}" =~ "^([^\\$U]*)\\$U([^\\$V]*)\\$V(.*)" ]]; then
708 eval ${1}[1]="\${BASH_REMATCH[1]}"
709 eval ${1}[2]="\${BASH_REMATCH[2]}"
710 eval ${1}[3]="\${BASH_REMATCH[3]}"
715 # fsyntax: strstrip <str>
716 # fdesc: delete blanks at the beginning and ending position.
720 sed -e "s/^[[:blank:]]*//g; s/[[:blank:]]*$//g" <<< "$1"
723 # $ if [[ "<cataid>" =~ \<([A-Za-z0-9_ ]+)\> ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
724 # $ abc='\
<([[:alnum
:]]*)\
>'; if [[ "<cataid>" =~ $abc ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
726 # $ abc='\
<([[:alnum
:]]*)\
>'; if [[ "<cataid> [type] name \"desc\" [ftype]" =~ \<$abc\>[\ \t]+\[([[:alnum:]]+)*\][\ \t]+([[:alnum:]]+)[\ \t]+\"([[:alnum:]]*)\"[\ \t]+\[([[:alnum:]]*)\].* ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
727 # xxxxxxxx <cataid> [type] name "desc" [ftype] cataid type name desc ftype xxxxxxxx
728 # $ abc='([[:alnum
:]]*)'; if [[ "<cataid> [type] name \"desc\" [ftype]" =~ \<$abc\>[\ \t]+\[$abc\][\ \t]+$abc[\ \t]+\"$abc\"[\ \t]+\[$abc\].* ]]; then echo match[0]=${BASH_REMATCH[0]}; echo match[1]=${BASH_REMATCH[1]}; echo match[2]=${BASH_REMATCH[2]}; echo match[3]=${BASH_REMATCH[3]}; echo match[4]=${BASH_REMATCH[4]}; echo match[5]=${BASH_REMATCH[5]}; fi
729 # match[0]=<cataid> [type] name "desc" [ftype]
736 # $ abc='([[:alnum
:]]*)+'; fmt="((\<[[:alnum:]]*)\>[\ \t]*)*"; echo fmt="\"$fmt\""; if [[ "<cataid> <type> <name> <desc> [ftype]" =~ $fmt ]]; then echo match[0]=${BASH_REMATCH[0]}; echo match[1]=${BASH_REMATCH[1]}; echo match[2]=${BASH_REMATCH[2]}; echo match[3]=${BASH_REMATCH[3]}; echo match[4]=${BASH_REMATCH[4]}; echo match[5]=${BASH_REMATCH[5]}; fi
739 # fsyntax: fmt_str_to_matching_regex
745 # VNAME_ARRAY, var defined in STR_FMT.
746 # STR_REGEX, reg-expr string for matching variable in STR_FMT.
748 fmt_str_to_matching_regex ()
760 # STR_FMT="$(attr_get STR_FMT)"
761 [[ -z $STR_FMT ]] && err "fmt_str_to_matching_regex(): STR_FMT is null.\n" && return 0
763 if [[ -n $SEPCHAR ]]; then
770 # dbgoutd "array[]=${array[@]}\n"
772 i=$(( ${#array[@]} - 1 ))
773 [[ $i -lt 0 ]] && err "fmt_str_to_matching_regex(): array matching size err.\n" && return 1
776 vname="${array[$i]:2:-1}"
777 declare -g "VNAME_ARRAY[$i]=$vname"
779 if [[ -v ${vname}_REGEX ]]; then
780 eval ${vname}="\$(${vname}_REGEX}"
782 # declare -g "${vname}=\"([[:alnum:]_]*)\""
783 declare -g "${vname}=\"([^\\${SEPCHAR}*)\""
786 STR_FMT="${STR_FMT//@{$vname}/${!vname}}"
793 # get regex format string 'fmt', which is used for variable name matching.
795 fmt=`echo "$STR_FMT" | sed -e 's
/\
(.
[@
][{][[:alnum
:]_
]*[}].\
)/(\
1)/g
'`
796 fmt=`echo "$fmt" | sed -e "s/\([[:punct:][:blank:]]\)/\\\\\\\\\1/g"`
797 fmt="$(echo "$fmt" | sed -e "s/\\\\\([\(\)\<\>]\\)/\1/g")"
798 fmt=`echo "$fmt" | sed -e 's
/\\\@
\\\
{[[:alnum
:]_
]*\\\
}/@
\\\\\
{[[:alnum
:]]*}/g
'`
799 #fmt=`echo "$STR_FMT" | sed -e 's
/@
{[[:alnum
:]_
]*}/(.?@
\\\\\
{[[:alnum
:]]*}.?
)/g
'`
800 #if [[ "$STR_FMT" =~ $fmt ]]; then echo BASH_REMATCH=${BASH_REMATCH[@]}; fi
802 # 1.regex matching in STR_FMT to get the variable name.
804 if [[ "$STR_FMT" =~ $fmt ]]; then
805 echo BASH_REMATCH=${BASH_REMATCH[@]}
807 # variable relative process
808 i="$(( ${#BASH_REMATCH[@]} - 1 ))"
809 [[ $i -le 0 ]] && err "fmt_str_to_matching_regex(): no string matching.\n" && return 1
813 vname="${BASH_REMATCH[$i]:3:-2}"
815 # dbgoutd "\${vname}=${vname}\n"
816 [[ -z "${vname}" ]] && continue
817 VNAME_ARRAY[$((i-1))]="${vname}"
818 # dbgoutd "\${BASH_REMATCH[$i]}=\"${BASH_REMATCH[$i]}\"\n"
819 if [[ -v ${vname}_REGEX ]]; then
820 eval ${vname}="\$(${vname}_REGEX}"
822 leftchar="${BASH_REMATCH[$i]:0:1}"
823 # use minus signature after ':', append a blank. or it
824 # will be treated as an initial expr.
825 rightchar="${BASH_REMATCH[$i]: -1:1}"
826 if [[ "${PAIRCHARS//$leftchar$rightchar/}" != "${PAIRCHARS}" ]]; then
827 #eval "${vname}=\"\[$leftchar\]([^\\$rightchar]*)\[$rightchar\]\""
828 # append three '\' before
$rightchar, if it is
'"', one
'\' mask
829 # it's particular
function, it
's equal to no mask.
830 eval declare -g "${vname}=\"([^\$rightchar]*)\""
832 eval declare -g "${vname}=\"([[:alnum:]_]*)\""
834 # dbgoutd "$vname = ${leftchar} ${!vname} ${rightchar}\n"
837 # save it to correspondding domain.
838 # attr_create $1::${vname}="${!vname}"
839 #eval ${vname}="${!vname}"
842 # 2.if not match, use single var reg-expr matching.
846 if [[ "$fmt" =~ [.]?@{([[:alnum:]_]*)}[.]? ]]; then
847 VNAME_ARRAY[$i]="${BASH_REMATCH[1]}"
848 str="${BASH_REMATCH[1]}_REGEX"
849 [[ ! -v $str ]] && str="${BASH_REMATCH[1]}_regex"
850 [[ ! -v $str ]] && str="GENERAL_REGEX"
852 eval fmt="\${fmt/${BASH_REMATCH[0]}/${!str}}"
858 if [[ "$(attr_get $vname)" =~ ${fmt} ]]; then
859 if [[ "${#BASH_REMATCH[@]}" != "$i" ]]; then
860 for ((; i>0; i--)); do
861 # TBD: set variable by attr_declare, it save data with domain pfx.
862 declare -g VNAME_ARRAY[$i]="${BASH_REMATCH[$i]}"
867 # 3.if not match, use analysis loop
868 if [[ -z "${VNAME_ARRAY[@]}" ]]; then
872 if [[ "${data:0:1}" == '@
' ]]; then
874 BASH_REMATCH[$i]="$vname"
876 if [[ -v ${vname}_REGEX ]]; then
877 eval ${vname}="\$(${vname}_REGEX}"
879 # save it to correspondding domain.
880 VNAME_ARRAY[$i]="${vname}"
881 eval $vname="\${!vname}"
885 rightchar=${data:0:1}
886 if [[ ! -v ${vname}_REGEX ]]; then
887 if [[ "$PAIRCHARS" =~ "${leftchar}${rightchar}" ]]; then
888 eval ${vname}="\[${leftchar}}\]([^\\${rightchar}]*)\[${rightchar}\]}"
890 eval $vname="([[:alnum:]_]*)"
893 # save it to correspondding domain.
894 VNAME_ARRAY[$i]="${vname}"
895 eval $vname="\${!vname}"
897 leftchar=${data:0:-1}
899 done <<< "$(echo "${STR_FMT}" | sed -e $'s
/@
/\n@
/g
' | sed -e $'s
/}/}\n/g
')"
900 # done <<< "$(echo "${STR_FMT}" | sed -e $'s
/\\\
(@
{[[:alnum
:]_
]*}\\\
)/\n@
{\\\
1\n}/g
'"
904 [[ -z "${VNAME_ARRAY[@]}" ]] && return 1
906 # translate format string to regex string, store in node.
907 STR_FMT_BAK="${STR_FMT}"
909 LKJDS_TMP_FMT=`echo "$STR_FMT" | sed -e "s/\([[:punct:][:blank:]]\)/\\\\\\\\\1/g"`
910 LKJDS_TMP_FMT="$(echo "$LKJDS_TMP_FMT" | sed -e "s/\\\\\([\@\{\}\<\>]\\)/\1/g")"
911 strfmt @LKJDS_TMP_FMT
913 [[ -n "$LKJDS_TMP" ]] && declare -g STR_REGEX="${LKJDS_TMP}"
914 STR_FMT="${STR_FMT_BAK}"
919 # fsyntax: array_proc <str-var-name>
920 # fdesc: dispatch given string, and store it to corresponding var
936 i=$(( ${#VNAME_ARRAY[@]} - 1 ))
937 [[ $i -lt 0 ]] && err "array_proc(): array matching err.\n" && return 1
940 eval declare -g "${VNAME_ARRAY[$i]}=\"\${array[${i}]}\""
950 # fsyntax: regexpr_proc <str-var-name>
951 # fdesc: matching given string by $STR_REGEX, and store it to corresponding var
958 if [[ -n "${STR_REGEX}" ]]; then
960 elif [[ -n "$STR_FMT" ]]; then
961 fmt_str_to_matching_regex
968 # [[ '<1> [srcdir
] TestDir1
"test dir 1"' =~ \<([^\>]*)\>\ \[([^\]]*)\]\ ([[:alnum:]_]*)\ \"([^\"]*)\" ]] && echo BASH_REMATCH[@]=${BASH_REMATCH[@]}
969 # [[ <1> [srcdir] TestDir1 "test dir 1" =~ \<([^\>]*)\>\ \[([^\]]*)\]\ ([[:alnum:]_]*)\ \"([^\"]*)\" ]]
971 # [[ <1> [srcdir] TestDir1 "test dir 1" =~ <"([^>]*)">\ \["([^]]*)"\]\ ([[:alnum:]_]*)\ \""([^"]*)"\" ]]
972 # [[ <1> [srcdir] TestDir1 "test dir 1" =~ <([^>]*)> \[([^]]*)] ([[:alnum:]_]*) "([^"]*)" ]]
975 # echo "\${STR_REGEX}=${STR_REGEX}"
976 # do not use "" for matching format string.
977 if [[ "$1" =~ ${STR_REGEX} ]]; then
979 i=$(( ${#BASH_REMATCH[@]} - 1 ))
980 [[ $i -le 0 ]] && echo xxxxxxxxxxxxxxxxxxxxxxxx && return 1
983 eval declare -g "${VNAME_ARRAY[$((i-1))]}=\"${BASH_REMATCH[${i}]}\""
992 output_vname_array ()
994 local size=$(( ${#VNAME_ARRAY[@]} - 1 ))
997 for ((i=0; i<=size; i++))
999 eval tmp="${VNAME_ARRAY[$i]}"
1000 echo -ne "$tmp=${!tmp}; "
1005 METHOD_LIST="array regexpr pairchar "
1008 # this function maybe named as 'strmatch
'.
1009 # it can be used to formated file name generate and recognize.
1010 # it also can be used in regular formated single line doc,
1011 # or, it can be used in tui template controller for multi-editor controller.
1015 # fsyntax: str2var <string>
1016 # fdesc: matching the string in paramter $1. it need a reg-expr string var 'STR_REGEX
',
1017 # defined in environment variable. if not defined, generate it from STR_FMT with relative
1019 # str2var() is not used for general purpose, it's a formated string matching
function.
1020 # normally, the string is a file name, or formated line text, with some sperator.
1023 # SEPCHAR, seperate char used as $IFS.
1024 # STR_REGEX, reg-expr string for matching.
1025 # STR_FMT, if STR_REGEX not exist, use it to generate STR_REGEX.
1026 # STR, if $2 is not specified, use it as input string.
1027 # VNAME_ARRAY[], variable name stored in STR_FMT. if not specified,
1028 # it will be generated from STR_FMT again.
1029 # <VARS>, save variable string matched from $STR to variable named as
1030 # ${VNAME_ARRAY[@]}.
1032 # relative var: STR_FMT, STR_REGEX, SEPCHAR, PAIRCHAR, XXX_REGEX, VNAME_ARRAY
1038 string
="$(attr_get $1)"
1040 # dbgoutd "\$1=${string}\n"
1042 # dbgoutd "STR_FMT=$STR_FMT\n"
1045 if [[ -n $SEPCHAR ]]; then
1047 elif [[ -n $STR_REGEX ]]; then
1049 elif [[ -n $STR_FMT ]]; then
1050 fmt_str_to_matching_regex
1052 elif [[ -n $PAIRCHAR ]]; then
1058 if [[ -z ${VNAME_ARRAY[@]} ]]; then
1059 dbgoutd
"=======================\n"
1061 dbgoutd
"STR_FMT=$STR_FMT\n"
1062 fmt_str_to_matching_regex
1063 # dbgoutd "VNAME_ARRAY=${VNAME_ARRAY[@]}\n"
1066 dbgoutd
"\${VNAME_ARRAY[@]}=${VNAME_ARRAY[@]}\n"
1067 if [[ -n ${string} ]]; then
1068 if [[ ${1:0:1} == '@' ]]; then
1069 declare -g STR
="$(attr_get $1)"
1070 elif [[ -v ${string} ]]; then
1071 declare -g STR
="${!string}"
1073 declare -g STR
="${string}"
1075 elif [[ -v STR
]]; then
1077 elif [[ "$(readlink /proc/self/fd/0)" =~
'pipe:[' ]]; then
1080 # it only read short text string, that re-directed to str2var().
1081 # it can read multiline in a variable.
1085 read -d $
'\x00' -t 0.1 -r STR
1088 err
"string is not specified in paramter or $STR or stdin.\n"
1092 # dbgoutd "NCATAID=$NCATAID\n"
1093 # dbgoutd "NTYPE=$NTYPE\n"
1094 # dbgoutd "NNAME=$NNAME\n"
1095 # dbgoutd "NDESC=$NDESC\n"
1097 # dbgoutd "STR=${STR}\n"
1098 # dbgoutd "METHOD=${METHOD}\n"
1099 # dbgoutd "=============================\n"
1101 # using process function
1103 ${METHOD}_proc
"$string"
1104 if [[ $?
!= 0 ]]; then
1105 eval METHOD
=\
${METHOD_LIST#*$METHOD }
1106 [[ -z $METHOD ]] && break
1115 # fsyntax: templete <tmpl-file> [output-file]
1116 # fdesc: 对templete-file进行var-content-insert。
1121 if [[ -z $output ||
$output == "-" ]]; then
1124 cat $1 | strfmt_p2p |
$output
1131 ######################
1132 # section: file tail
1133 ######################
1141 # get format of string by the ext-name
1146 if [[ -n $fmt ]]; then
1147 strrvsfmt
"$1" "$fmt" "$3"
1149 fmt=$
(attr_get catalog
::$
(ext
)::regex
)
1150 if [[ -n "$STR_REGEX" ]]; then
1151 regex_str_dispatch
"$1" "$fmt" "$3"
1153 str2var_array
"$1" catalog
::$
(ext
)::syntax
"$3"
1160 str2var_proc
=strrvsfmt
1162 # fsyntax: regex_str_dispatch <str-var>
1163 # fdesc: recogonize string by reg-expr, and output sub-str to variables.
1164 regex_str_dispatch
()
1167 local vfmt
="${1}_fmt"
1173 fmt="$(attr_get $vfmt)"
1176 if [[ "$fmt" =~ @
{([[:alnum
:]_
]*)} ]]; then
1177 varlist
[$i]="${BASH_REMATCH[1]}"
1178 str
="${BASH_REMATCH[1]}_REGEX"
1179 [[ ! -v $str ]] && str
="${BASH_REMATCH[1]}_regex"
1180 [[ ! -v $str ]] && str
="GENERAL_REGEX"
1182 eval fmt="\${fmt/${BASH_REMATCH[0]}/${!str}}"
1188 if [[ "$(attr_get $vname)" =~
"${fmt}" ]]; then
1189 [[ "${BASH_REMATCH[@]}" != "$i" ]] && return 1
1190 for ((; i
>0; i--
)); do
1191 # TBD: set variable by attr_declare, it save data with domain pfx.
1192 declare -g ${varlist[$i]}="${BASH_REMATCH[$i]}"
1196 # if [[ "$(attr_get $vname)" =~ "$(attr_get $vfmt)" ]]; then
1197 # for ((i=0; i<${#BASH_REMATCH[@]}; i++)); do
1198 # attr_create ${3}::BASH_REMATCH_${i} = "${BASH_REMATCH[$i]}"
1203 # use char to seperate string.
1205 # fsyntax: str2var_array <str-var-name> <sepchar> <attr-var-name>
1206 # fdesc: dispatch given string, and store it to arr-name array.
1211 local sepchar
=$
(attr_get catalog
::$2::sepchar
)
1212 local wrap
=(attr_get catalog
::$2::wrap
[@
])
1221 for $
((i
=0; i
<${#array[@]}; i
++)); do
1222 if [[ "${wrap[@]}" =~ ${array[$i]:0:1} && "${wrap[@]}" =~ ${array[$i]:0:-1} ]]; then
1223 array[$i]=${array[$i]:1:-1}
1225 if [[ "${wrap[@]}" =~ ${array[$i]:0:1} && "${wrap[@]}" =~ ${array[$i]:0:-1} ]]; then
1226 array
[$i]=${array[$i]:1:-1}
1228 if [[ "${wrap[@]}" =~ ${array[$i]:0:1} && "${wrap[@]}" =~ ${array[$i]:0:-1} ]]; then
1229 array[$i]=${array[$i]:1:-1}
1232 name=$(attr_get ${2}::attr_idx[$i])
1234 attr_set ${3}::${name} = ${array[$i]}
1238 # strrvsfmt "<cataid1
> <type1
> <name1
> <desc1
> <ftype1
>" "<@
{cataid
}>\\\
<@
{type}>\\\
<@
{name
}>\\\
<@
{desc
}>\\\
<@
{ftype
}>" var
1239 # use string format defined for strfmt.
1245 local var_fmt="([[:alnum
:]_
]+)"
1248 # dispatch fmt str, and get the var-name list.
1249 # echo "aaa
=${aaa//@/$'\n'}"
1250 # echo "${aaa//@/$'\n'}" | while read data; do echo data=${data}; if [[ "$data" =~ .*\{([[:alnum:]]+)\}.
* ]]; then echo MATCH
=${BASH_REMATCH[1]}; fi; done
1253 if [[ "$data" =~ ^\
{([[:alnum
:]_
]+)\
} ]]; then
1254 # echo "vnamelist[$i]=${BASH_REMATCH[1]}"
1255 # echo "data=$var_fmt${data#*\}}"
1256 fmt+="$var_fmt${data#*\}}"
1258 vnamelist
[$i]="${BASH_REMATCH[1]}"
1263 done < <(echo "${2//@/$'\n'}")
1265 # reg-expr matching, and fill to the corresponding var under the domain of attr-var paramter given.
1266 # try this example string if there is some problem.
1267 #[[ "<cataid1> <type1> <name1> <desc1> <ftype1>" =~ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\> ]] && echo XXXXXXXXXXXXXXXXXXXX
1268 if [[ "${1}" =~
$fmt ]]; then
1269 [[ $
(( ${#vnamelist[@]} + 1 )) != ${#BASH_REMATCH[@]} ]] && return
1270 for ((i
=1; i
<${#BASH_REMATCH[@]}; i
++)); do
1271 echo ${3}::${vnamelist[$(($i - 1))]} = "${BASH_REMATCH[$i]}"
1272 # attr_create ${3}::${vnamelist[$i]} = "${BASH_REMATCH[1]}"
1278 strfmt_var_name_check_bak
()
1280 # for first loop, it use the idx value defined before.
1281 # for next loop, it use the idx value $i.
1282 # if idx is @ or no idx specified, it uses 0, it's equal
1283 # to i=0 in first loop.
1284 for ((i
=0; i
<cnt
; i
++)); do
1285 $vout="$(strfmt_pipe <<< \"\${$vname$idx}\")"
1286 # the first idx is setting before loop if cnt == 1.
1290 if [[ ${cnt} == 1 ]]; then
1291 if [[ -z $sfx && $idx == 0 ]]; then
1296 if [[ -z $sfx ]]; then
1299 eval vname
=\
${var%${BASH_REMATCH}}
1303 if [[ ${var} =~
"_FMT" ]]; then
1306 if [[ $cnt -ge 1 ]]; then
1307 # 不指定数组idx,变量为数组,XXX_FMT[@],输出到XXX[@]
1308 for ((; cnt
>=0; cnt--
)); do
1309 ## echo "${var}[$cnt]=\${${var}_FMT[$cnt]}"
1310 declare -g ${var}[$cnt]="$(strfmt_p2p < <(eval echo \"\${${var}_FMT[$cnt]}a
\"))"
1311 eval ${var}[$cnt]="\${${var}[$cnt]:0:-1}"
1314 # 指定idx的单个数组的元素,XXX_FMT[$i],输出到XXX[$i]
1315 # 非数组的元素,XXX_FMT,输出到XXX,即XXX_FMT[0],输出到XXX[0]
1316 if [[ -z $array ]]; then
1317 eval array
="[\${#${var}_FMT[@]}]"
1319 ## echo "${var}$array=\${${var}_FMT$array}"
1320 declare -g ${var}$array="$(strfmt_p2p < <(eval echo \"\${${var}_FMT$array}a
\"))"
1321 eval ${var}$array="\${${var}$array:0:-1}"
1323 elif [[ ${var} =~
"_fmt" ]]; then
1326 if [[ $cnt -ge 1 ]]; then
1327 # 不指定数组idx,变量为数组,XXX_FMT[@],输出到XXX[@]
1328 for ((; cnt
>=0; cnt--
)); do
1329 ## echo "${var}[$cnt]=\${${var}_fmt[$cnt]}"
1330 declare -g ${var}[$cnt]="$(strfmt_p2p < <(eval echo \"\${${var}_fmt[$cnt]}a
\"))"
1331 eval ${var}[$cnt]="\${${var}[$cnt]:0:-1}"
1334 # 指定idx的单个数组的元素,XXX_FMT[$i],输出到XXX[$i]
1335 # 非数组的元素,XXX_FMT,输出到XXX,即XXX_FMT[0],输出到XXX[0]
1336 if [[ -z $array ]]; then
1337 eval array
="[\${!${var}_fmt[@]}]"
1339 ## echo "${var}$array=\${${var}_fmt[$cnt]}"
1340 declare -g ${var}$array="$(strfmt_p2p < <(eval echo \"\${${var}_fmt$array}a
\"))"
1341 eval ${var}$array="\${${var}${array}:0:-1}"
1343 elif [[ -n ${array} ]]; then
1345 # 指定idx的单个数组的元素,XXX[$i],输出到XXX[0]
1346 # xxx: 对于XXX[0],输出到XXX[0],但实际不应这么使用。
1347 ## echo "${var}[$array]=\${${var}$array}"
1348 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a
\"))"
1349 eval ${var}[0]="\${${var}[0]:0:-1}"
1351 if [[ ${cnt} == 1 ]]; then
1353 if [[ -v ${var}[0] ]]; then
1354 # 其中一个idx为0,使用非0的idx值。
1357 eval array
=( \
${#$var[@]} )
1358 array
="[${array[1]}]"
1359 ## echo "${var}[0]=\${${var}$array}"
1360 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a
\"))"
1361 eval ${var}[0]="\${${var}[0]:0:-1}"
1364 ### echo "an array var '$var' without index or _fmt or _FMT surfix cannot be used."
1366 eval echo "\${${var}[@]}"
1368 elif [[ ${cnt} -gt 1 ]]; then
1370 ### echo "an array var '$var' without index or _fmt or _FMT surfix cannot be used."
1372 eval echo "\${${var}[@]}"
1375 # 非数组的元素,XXX,输出到stdout
1376 eval array
="[\${!${var}[@]}]"
1377 if [[ $array == "[0]" ]]; then
1378 ## echo "${var} ==> stdout"
1379 strfmt_p2p
< <(echo "${!var}")
1381 # xxx: 这里末尾的字符不需要添加,调试用
1382 ## echo "${var}[$array]=\${${var}$array}"
1383 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a
\"))"
1384 eval ${var}[0]="\${${var}[0]:0:-1}"
1391 # fsyntax: strfmt_ln
1392 # fdesc: process one line string to output.
1413 eval line
="\${MAPFILE${embcnt}[$idx]}"
1415 # todo:这里需要对输出的字符串,进行eval/evaln的处理。
1418 # 屏蔽符"\\\\"在shell命令行解析成‘\\‘,所以实际字符串操作是是'\\'转换成'\\\\',但单个的'\'不进行replace。
1419 # line="${line//\\\\/\\\\\\\\}"
1420 # 当字符串转义后,'\\\\'转换成'\\',等同于字符串转义操作对'\\'不进行转义,使得奇数个'\'时进行转义,
1421 # 如果未转义,\后的字符为非转义字符。如果奇数个'\'之后是'&','&'replace成$’\n'再以$’\n'分隔成数组时,
1422 # 可根据'\'为奇数个,表示换行符replace之前被'\'屏蔽,&不作为变量标记符号使用。
1425 if [[ $STRFMT_EVALN == "eval" ]]; then
1426 ## eval echo "xxxxxxxxxxx=\"$line\""
1427 line
="`eval echo -n \"\\\"$line\\\"\"`"
1429 ## echo -n${STRFMT_TRANS} "${line[0]}"
1430 elif [[ $STRFMT_EVALN == "evaln" ]]; then
1431 line
="`evaln echo -n \"$line\"`"
1434 # echo "STRFMT_TRANS=$STRFMT_TRANS"
1436 # fmt变量以{}之间的字符串为变量,进行字符串插入
1443 bakline
=( ${bakline} )
1446 cnt
=$
((${#line[@]}-1))
1449 echo -n${STRFMT_TRANS} "${line[0]}"
1450 for ((i
=1; i
<cnt
; i
++)); do
1451 case "${line[$i]:0:1}" in
1453 [[ ! "${line[$i]}" =~
")" ]] && echo -ne "err($idx): ')' missing.\n" >&2 && break
1456 reststr
="${line[$i]#*\)}"
1457 bakreststr
="${bakline[$i]#*\)}"
1462 [[ ! "${line[$i]}" =~
"}" ]] && echo -ne "err($idx): '}' missing.\n" >&2 && break
1466 # STRFMT_PARAM=( ${var} )
1475 if [[ ${var:1:1} != ':' ]]; then
1478 var
="${STRFMT_DOMAIN}_${var}"
1480 # ":",被dup的section作用域
1482 var
="${STRFMT_DOMAIN}${var}"
1490 # echo -e "\nvar=$var\n"
1491 reststr
="${line[$i]#*\}}"
1492 bakreststr
="${bakline[$i]#*\}}"
1496 # 变量名称中不使用转义符,所以不需要判断行末的'\',存在'\'即是不正确的变量名
1497 if [[ -z "$var" ||
"${var}" =~
[^
[:alnum
:]_-
]+ ||
${#line[$i]} -gt 256 ]]; then
1499 echo -ne "err: symbol name '$var' is not valid.\n" >&2
1501 elif [[ ! $var =~
[^
0-9] ]]; then
1502 # 如果为数字,表示@{var paramlist}中的参数id。
1503 # 格式字符串使用时的函数参数$1不使用,而@{1}用于格式字符串的参数
1504 if [[ -n ${STRFMT_PARAM[${var}]} ]]; then
1505 # echo "strfmt \${STRFMT_PARAM[${var}]}=${STRFMT_PARAM[${var}]}"
1506 echo -n${STRFMT_TRANS} "${STRFMT_PARAM[${var}]}"
1508 echo -ne "warn
: paramter
${var} is not valid.
\n" >&2
1512 # 变量已定义,则调用strfmt_v2p()函数解析并输出
1513 if [[ -n ${!var} ]]; then
1514 # echo var="strfmt
$var"
1518 [[ $ret != 0 ]] && return 3
1520 echo -ne "warn
: symbol
&${line[$i]}& is not defined.
\n" >&2
1528 id=$((${#bakreststr}-1))
1530 baktmp="${bakreststr}"
1531 [[ "${baktmp:$id:1}" != "\\" ]] && echo -n${STRFMT_TRANS} "${tmp}" && continue
1533 str=${baktmp##*[^\\]}
1534 if [[ $((${#str}%2)) == 1 ]]; then
1535 # 再将字符串中的'\\'替换为'\',进行'\\'的转义操作。
1537 echo -n${STRFMT_TRANS} "${tmp}@
"
1540 echo -n${STRFMT_TRANS} "${tmp}"
1544 while [[ $i < $cnt ]]; do
1545 id=$((${#line[$i]}-1))
1547 baktmp="${bakline[$i]}"
1548 [[ "${baktmp:$id:1}" != "\\" ]] && echo -n${STRFMT_TRANS} "${tmp}" && break
1550 str=${baktmp##*[^\\]}
1551 if [[ $((${#str}%2)) == 1 ]]; then
1552 # 再将字符串中的'\\'替换为'\',进行'\\'的转义操作。
1554 echo -n${STRFMT_TRANS} "${tmp}@
"
1557 echo -n${STRFMT_TRANS} "${tmp}"
1565 # fsyntax: cat xxx | strfmt_p2p
1566 # fdesc: 不指定第二个参数时,$1格式解析后输出到$2。第二个参数为-时输出到stdout
1575 embcnt=$(( embcnt+1 ))
1577 vname=MAPFILE${embcnt}
1579 declare -g -a ${vname}
1580 while read -r data; do
1581 eval "${vname}+=( \"\
$data\" )"
1583 if [[ $idx -gt 1 ]]; then
1586 if [[ $idx == 0 ]]; then
1591 eval data=\${$vname[$((idx-1))]}
1592 if [[ -n $data ]]; then
1593 strfmt_ln $((idx-1))
1599 [[ $idx -gt 1 ]] && echo
1601 vname="vname
[$
((idx-1
))]"
1602 if [[ -n ${!vname} ]]; then
1603 strfmt_ln $((idx-1)) "${!vname}"
1606 embcnt=$(( embcnt-1 ))
1607 unset MAPFILE${embcnt}
1613 # fsyntax: strfmt_v2p <str-var>
1614 # fdesc: 不指定第二个参数时,$1格式解析后输出到$2第二个参数为-时输出到stdout
1617 # echo strfmt_v2p\($1\)
1618 strfmt_p2p < <(echo -n "${!1}"; echo)
1622 # fsyntax: strfmt <str-var>
1623 # fdesc: $1格式解析后输出到$2。不指定第二个参数时,或第二个参数为-时,输出到stdout
1631 # eval vname="\
${!${1}*}"
1634 [[ -z $var ]] && return
1637 if [[ ${var:0:1} == "@
" ]]; then
1638 if [[ ${var:1:1} == "(" ]]; then
1639 # TBD: check '@', and check the attr after it.
1643 elif [[ ${var:1:1} == "{" ]]; then
1648 STRFMT_PARAM=( $var )
1651 if [[ ${var:0:1} == ':' ]]; then
1652 if [[ ${var:1:1} == ':' ]]; then
1655 var="${STRFMT_DOMAIN}_
${var}"
1657 # ":",被dup的section作用域
1658 # :使用定义类型的domain,当前domain之后使用。
1660 var="${STRFMT_DOMAIN}${var}"
1662 elif [[ ${var:0:1} == '!' ]]; then
1667 # 不使用:,不添加domain,以普通环境变量使用。
1674 if [[ ${var} =~ "[" ]]; then
1676 array="[${array%%]*}]"
1677 [[ "$array" == "[*]" || "$array" == "[@
]" ]] && array=""
1680 ## vname="${var}${array}"
1682 if [[ -z $array ]]; then
1683 eval cnt=\$\(\( \${\#${var}[@]} - 1 \)\)
1689 # echo -n "STRFMT_PARAM
=${STRFMT_PARAM[@]}"
1690 if [[ ! "$var" =~ [^0-9] ]]; then
1691 # 如果为数字,表示@{var paramlist}中的参数id。
1692 # 格式字符串使用时的函数参数$1不使用,而@{1}用于格式字符串的参数
1693 if [[ -n ${STRFMT_PARAM[${var}]} ]]; then
1694 # echo "strfmt \
${STRFMT_PARAM[${var}]}=${STRFMT_PARAM[${var}]}"
1695 echo -n${STRFMT_TRANS} "${STRFMT_PARAM[${var}]}"
1698 echo -ne "warn: paramter ${var} is not valid.\n" >&2
1704 # 参数指定的变量xxx已定义,或xxx未定义,但xxx[]数组有定义,且只包含一个元素
1705 if [[ -v "${var}" ||
$cnt -ge 0 ]]; then
1706 # todo:这里需要对输入、输出的变量进行设置。
1708 strfmt_var_name_check
"$var"
1709 elif [[ "$(readlink /proc/self/fd/0)" =~
'pipe:[' ]]; then
1712 echo "no input data or no variable specified."
1719 abc
="aaaaaaaaaaaaaa"
1723 echo XXXXXXXXXXXXXXXXXXXXXXXXXX
1727 # use reloadshlib strfmt.shlib to load this lib, and open this invoking to debug
1728 # code in tesing mode.