20230322
[shlib.git] / shlib / strfmt-org.shlib
blobac79a8f1be13e3944c2930836372371c4223d055
1 #!/bin/bash
2 ############################################################
3 # source: strfmt.shlib
4 # author: devenkong(18151155@qq.com)
5 # date: 2022-04-30
6 ############################################################
7 # note:
8 # strfmt函数是字符串中@{}变量的expanssion。不同于${}环境变量的
9 # expanssiin的是,@{}的expanssion输出到pipeline,且可以嵌套使用,
10 # 且只输出到pipeline。与strfmt类似的函数evaln实现的是字符串的多重
11 # eval,但是eval操作时,是将${}环境变量的内容expanssion到命令行,
12 # 多次expansion的方法。这在环境变量内包含的字符串内容较长,且变量嵌套
13 # 层数较多时,包含字符串的重复操作。
14 # 字符串进行@{}的解析之外,还可设置eval进行${}的expanssion,
15 # 和\特殊功能屏蔽符解析,以及使用trans进行\转义符的解析。
16 # strfmt函数的命令行程序为evstrn,将strfmt字符串的三种形式以参数
17 # 进行设置。
18 # strfmt的常用的用途,可用于templete文件中插入一些填充的信息,
19 # 或是应用中定义格式字符串,在使用时调用strfmt,根据环境变量内容,输出
20 # 不同运行环境下的字符串内容。例如系统中不同的软件的安装路径不同,使用
21 # strfmt定义的字符串,根据软件包名称等信息,输出一个软件包的安装路径。
22 # paths.shlib中定义的格式化字符串即是这个用途。
23 ############################################################
24 # date: 2022-10-03
25 ############################################################
26 # note:
27 # strfmt函数中的变量操作和作用域的功能特性,抽象到attr.shlib
28 # 库文件中。所以需要将代码中对应的功能进行调整。
29 # 属性的表示,以__替换::,用于体现变量的层次关系。原有代码中未将
30 # 属性的代码以一个功能模块抽象成一组函数。
31 ############################################################
34 # 打开脚本中使用alias功能,否则脚本中使用alias无效,而在命令行才有效。
35 shopt -s expand_aliases
37 # todo:
38 # @ strfmt解析的var,添加domain。${var domain}
39 # @
42 #include gplib.shlib
45 ######################
46 # section: 公用注释信息
47 ######################
51 ######################
52 # section: 变量定义
53 ######################
56 STRFMT_DOMAIN=
57 STRFMT_PARAM=
59 export embcnt=0
62 ######################
63 # section: private函数
64 ######################
67 # fsyntax: strfmt_ln
68 # fdesc: process one line string to output.
69 strfmt_ln ()
71 local idx=$1
72 local i
73 local j=0
74 local cnt
75 local tmp
76 local baktmp
77 local flag=0
78 local var
79 local varin=$1
80 local varout=$2
81 local line
82 local id
83 local str
84 local bak
85 local bakline
87 local vname
89 eval line="\${MAPFILE${embcnt}[$idx]}"
91 # todo:这里需要对输出的字符串,进行eval/evaln的处理。
93 # c-style转义符解析。
94 # 屏蔽符"\\\\"在shell命令行解析成‘\\‘,所以实际字符串操作是是'\\'转换成'\\\\',但单个的'\'不进行replace。
95 # line="${line//\\\\/\\\\\\\\}"
96 # 当字符串转义后,'\\\\'转换成'\\',等同于字符串转义操作对'\\'不进行转义,使得奇数个'\'时进行转义,
97 # 如果未转义,\后的字符为非转义字符。如果奇数个'\'之后是'&','&'replace成$’\n'再以$’\n'分隔成数组时,
98 # 可根据'\'为奇数个,表示换行符replace之前被'\'屏蔽,&不作为变量标记符号使用。
99 # 这里屏蔽'\\'的转义操作。
100 bakline="$line"
101 if [[ $STRFMT_EVALN == "eval" ]]; then
102 ## eval echo "xxxxxxxxxxx=\"$line\""
103 line="`eval echo -n \"\\\"$line\\\"\"`"
104 # STRFMT_TRANS=""
105 ## echo -n${STRFMT_TRANS} "${line[0]}"
106 elif [[ $STRFMT_EVALN == "evaln" ]]; then
107 line="`evaln echo -n \"$line\"`"
110 # echo "STRFMT_TRANS=$STRFMT_TRANS"
112 # fmt变量以{}之间的字符串为变量,进行字符串插入
113 OLD_IFS=$IFS
114 # IFS=$'\n'
115 IFS='@'
116 line+="@x"
117 line=( ${line} )
118 bakline+="@x"
119 bakline=( ${bakline} )
120 IFS=$OLD_IFS
122 cnt=$((${#line[@]}-1))
123 # echo cnt=$cnt
125 echo -n${STRFMT_TRANS} "${line[0]}"
126 for ((i=1; i<cnt; i++)); do
127 case "${line[$i]:0:1}" in
128 '(' )
129 [[ ! "${line[$i]}" =~ ")" ]] && echo -ne "err($idx): ')' missing.\n" >&2 && break
130 var="${line[$i]:1}"
131 var="${var%%\)*}"
132 reststr="${line[$i]#*\)}"
133 bakreststr="${bakline[$i]#*\)}"
134 $var
136 '{' )
137 # echo "@@@@@@@@@@"
138 [[ ! "${line[$i]}" =~ "}" ]] && echo -ne "err($idx): '}' missing.\n" >&2 && break
139 var="${line[$i]:1}"
140 var="${var%%\}*}"
142 # STRFMT_PARAM=( ${var} )
143 # var=$STRFMT_PARAM
144 case ${var:0:1} in
145 '!' )
146 # 环境变量的引用
147 var="${var:1}"
148 var=${!var}
150 ':' )
151 if [[ ${var:1:1} != ':' ]]; then
152 # "::",环境变量
153 var="${var:2}"
154 var="${STRFMT_DOMAIN}_${var}"
155 else
156 # ":",被dup的section作用域
157 var="${var:1}"
158 var="${STRFMT_DOMAIN}${var}"
162 # 当前section的作用域
165 esac
166 # echo -e "\nvar=$var\n"
167 reststr="${line[$i]#*\}}"
168 bakreststr="${bakline[$i]#*\}}"
169 #strfmt_v2p "$var"
171 # 变量解析后输出对应字符串
172 # 变量名称中不使用转义符,所以不需要判断行末的'\',存在'\'即是不正确的变量名
173 if [[ -z "$var" || "${var}" =~ [^[:alnum:]_-]+ || ${#line[$i]} -gt 256 ]]; then
174 # 非变量有效字符,不进行字符串输出
175 echo -ne "err: symbol name '$var' is not valid.\n" >&2
176 return 1
177 elif [[ ! $var =~ [^0-9] ]]; then
178 # 如果为数字,表示@{var paramlist}中的参数id。
179 # 格式字符串使用时的函数参数$1不使用,而@{1}用于格式字符串的参数
180 if [[ -n ${STRFMT_PARAM[${var}]} ]]; then
181 # echo "strfmt \${STRFMT_PARAM[${var}]}=${STRFMT_PARAM[${var}]}"
182 echo -n${STRFMT_TRANS} "${STRFMT_PARAM[${var}]}"
183 else
184 echo -ne "warn: paramter ${var} is not valid.\n" >&2
185 return 2
187 else
188 # 变量已定义,则调用strfmt_v2p()函数解析并输出
189 if [[ -n ${!var} ]]; then
190 # echo var="strfmt $var"
191 strfmt "$var"
192 ret=$?
193 # echo ret=$ret
194 [[ $ret != 0 ]] && return 3
195 else
196 echo -ne "warn: symbol &${line[$i]}& is not defined.\n" >&2
197 return 2
201 esac
203 # 以未eval的字符串的\进行判断
204 id=$((${#bakreststr}-1))
205 tmp="${reststr}"
206 baktmp="${bakreststr}"
207 [[ "${baktmp:$id:1}" != "\\" ]] && echo -n${STRFMT_TRANS} "${tmp}" && continue
209 str=${baktmp##*[^\\]}
210 if [[ $((${#str}%2)) == 1 ]]; then
211 # 再将字符串中的'\\'替换为'\',进行'\\'的转义操作。
212 tmp=${reststr%\\}
213 echo -n${STRFMT_TRANS} "${tmp}@"
214 : $(( i++ ))
215 else
216 echo -n${STRFMT_TRANS} "${tmp}"
217 continue
220 while [[ $i < $cnt ]]; do
221 id=$((${#line[$i]}-1))
222 tmp="${line[$i]}"
223 baktmp="${bakline[$i]}"
224 [[ "${baktmp:$id:1}" != "\\" ]] && echo -n${STRFMT_TRANS} "${tmp}" && break
226 str=${baktmp##*[^\\]}
227 if [[ $((${#str}%2)) == 1 ]]; then
228 # 再将字符串中的'\\'替换为'\',进行'\\'的转义操作。
229 tmp=${tmp%\\}
230 echo -n${STRFMT_TRANS} "${tmp}@"
231 : $(( i++ ))
232 else
233 echo -n${STRFMT_TRANS} "${tmp}"
234 break
236 done
237 done
241 # fsyntax: cat xxx | strfmt_p2p
242 # fdesc: 不指定第二个参数时,$1格式解析后输出到$2。第二个参数为-时输出到stdout
243 strfmt_p2p ()
245 local idx=0
246 local data
247 local flag=0
248 local vname
249 local data
251 embcnt=$(( embcnt+1 ))
253 vname=MAPFILE${embcnt}
254 unset $vname
255 declare -g -a ${vname}
256 while read -r data; do
257 eval "${vname}+=( \"\$data\" )"
259 if [[ $idx -gt 1 ]]; then
260 echo
262 if [[ $idx == 0 ]]; then
263 : $(( idx++ ))
264 continue
267 eval data=\${$vname[$((idx-1))]}
268 if [[ -n $data ]]; then
269 strfmt_ln $((idx-1))
272 : $(( idx++ ))
273 done
275 [[ $idx -gt 1 ]] && echo
277 vname="vname[$((idx-1))]"
278 if [[ -n ${!vname} ]]; then
279 strfmt_ln $((idx-1)) "${!vname}"
282 embcnt=$(( embcnt-1 ))
283 unset MAPFILE${embcnt}
285 return 0
289 # fsyntax: strfmt_v2p <str-var>
290 # fdesc: 不指定第二个参数时,$1格式解析后输出到$2第二个参数为-时输出到stdout
291 strfmt_v2p ()
293 # echo strfmt_v2p\($1\)
294 strfmt_p2p < <(echo -n "${!1}"; echo)
299 ######################
300 # section: public函数
301 ######################
303 #####################################################################
304 # [字符串操作函数]
305 #####################################################################
309 # @ 多行字符串的fmt,输出通常为pipe或file,输出到var,通常使用evaln。
310 # # 字符串处理中,以pipe输出,逐行处理时,以var+=或var+=( $content )保存到环境变量。
311 # # 输出到file,实际以pipe输出的重定向来实现。所以strfmt的输出,都以stdout为输出。
313 # @ 输入包括var、pipe、file。
314 # # 以var为输入,用于环境变量定义的格式化字符串。
315 # # 以pipe为输入,通常输入的字符串内容较长。可以和其它程序以pipe连接,形成字符串处理链。
316 # # 以file为输入,输入的字符串内容较长,且以文件的形式存储。
317 # @ 无论是哪种输入,都转换为str的逐行处理,所以定义一个单行处理的alias命令行。
318 # # 以参数var为输入,stdout为输出。
322 # 环境变量的expanssion使用evaln进行多重eval,
323 # 多行字符串和pipe字符串的expanssion使用strfmt。
324 # 文本文件的expansion使用tmpl调用strfmt linedata,
325 # linedata存放单行字符串。
330 # 字符串包含的功能:
331 # @ eval,进行$的expanssion和\特殊字符的屏蔽
332 # @ evaln,n次eval
333 # @ -e,与echo中的-e参数一样,对字符串中\转义符的解析
334 # @ fmt,对字符串中&var&的内容进行插入
335 # @
337 # @ evaln:字符串的evaln,变量之后的@e只对参数变量进行\转义符解析,@E对字符串中的变量进行转义符的循环解析。
338 # @ strfmt:只进行&var&变量的插入。参数为var_fmt或VAR_FMT或var[1]时,输出到$var变量,其它输出到stdout。
339 # @ STRFMT_EVALN:对于fmt字符串进行eval输出,再进行变量内容的插入。设置为N或N进行evaln,其它为eval,未定义不进行eval。
340 # @ STRFMT_TRANS:对fmt字符串进行\转义符的输出。
341 # @ strfmtset:设置eval、evaln、trans参数。
344 # syntax: evaln <var-name>
345 # fdesc: 函数将指定var中的变量expanssion。字符串中的var在字符串expanssion后与其它字符串连接,
346 # 会使var的名称字符串不同,使var在expanssion时异常。须在字符串中以${var}的格式使用。
347 # fparam:
348 # var-name: eval的字符串变量名称。如果为_FMT或_fmt的sfx,expanssion的字符串保存到不含
349 # sfx的变量中。如果变量不含sfx,在stdout输出字符串。
350 # e: 只对变量字符串进行转义符解析。该参数以vname@e的形式使用。
351 # E: 对变量及其包含的变量中的转义符进行解析。
353 alias evaln='
355 local evstrn_i
356 local evstrn_cnt=100
357 local evstrn_tmp
358 local evstrn_vname=
359 local evstrn_e=""
361 read -t 1 evstrn_tmp
363 if [[ "$evstrn_tmp" =~ "@" ]]; then
364 evstrn_e=${evstrn_tmp##*@}
365 evstrn_tmp=${evstrn_tmp%%@*}
368 if [[ ${evstrn_tmp} =~ "_FMT" || ${evstrn_tmp} =~ "_fmt" ]]; then
369 evstrn_vname=${evstrn_tmp%%_*}
370 declare ${evstrn_vname}="${!evstrn_tmp}"
371 evstrn_tmp=0
372 else
373 evstrn_vname="$evstrn_tmp"
374 evstrn_tmp=1
377 if [[ "$evstrn_e" == E ]]; then
378 evstrn_e=e
379 elif [[ "$evstrn_e" == e ]]; then
380 declare ${evstrn_vname}="`echo -ne \"${!evstrn_vname}\"`"
381 evstrn_e=""
382 else
383 evstrn_e=""
386 for (( evstrn_i=0; evstrn_i < evstrn_cnt; evstrn_i++ )); do
387 eval ${evstrn_vname}="$(echo -n${evstrn_e} "\"${!evstrn_vname}\"")"
388 [[ ! "${!evstrn_vname}" =~ "\$" ]] && break
389 done
391 [[ "$evstrn_tmp" == 1 ]] && echo -n${evstrn_e} "${!evstrn_vname}"
393 unset evstrn_i
394 unset evstrn_cnt
395 unset evstrn_tmp
396 unset evstrn_vname
397 unset evstrn_e
398 } <<< '
403 # fsyntax: strfmt <str-var>
404 # fdesc: $1格式解析后输出到$2。不指定第二个参数时,或第二个参数为-时,输出到stdout
405 strfmt ()
407 local var="$@"
408 local array=""
409 local vname=
410 local cnt
412 # eval vname="\${!${1}*}"
413 # echo vname=$vname
415 [[ -z $var ]] && return
417 # @ 格式的变量名称
418 if [[ ${var:0:1} == "@" ]]; then
419 if [[ ${var:1:1} == "(" ]]; then
420 # TBD: check '@', and check the attr after it.
421 var="${var:2:-1}"
422 $var
423 return $?
424 elif [[ ${var:1:1} == "{" ]]; then
425 var="${var:2:-1}"
426 else
427 var="${var:1}"
429 STRFMT_PARAM=( $var )
430 var=$STRFMT_PARAM
431 # echo "var=$var"
432 if [[ ${var:0:1} == ':' ]]; then
433 if [[ ${var:1:1} == ':' ]]; then
434 # "::",使用当前domain。
435 var="${var:2}"
436 var="${STRFMT_DOMAIN}_${var}"
437 else
438 # ":",被dup的section作用域
439 # :使用定义类型的domain,当前domain之后使用。
440 var="${var:1}"
441 var="${STRFMT_DOMAIN}${var}"
443 elif [[ ${var:0:1} == '!' ]]; then
444 # 环境变量的引用
445 var="${var:1}"
446 var=${!var}
447 else
448 # 不使用:,不添加domain,以普通环境变量使用。
451 var="${var//:/_}"
454 # 单个item的数组
455 if [[ ${var} =~ "[" ]]; then
456 array="${var#*[}"
457 array="[${array%%]*}]"
458 [[ "$array" == "[*]" || "$array" == "[@]" ]] && array=""
459 var="${var%%[*}"
461 ## vname="${var}${array}"
462 # echo vname=$vname
463 if [[ -z $array ]]; then
464 eval cnt=\$\(\( \${\#${var}[@]} - 1 \)\)
465 # echo "var=$var"
466 else
467 cnt=0
470 # echo -n "STRFMT_PARAM=${STRFMT_PARAM[@]}"
471 if [[ ! "$var" =~ [^0-9] ]]; then
472 # 如果为数字,表示@{var paramlist}中的参数id。
473 # 格式字符串使用时的函数参数$1不使用,而@{1}用于格式字符串的参数
474 if [[ -n ${STRFMT_PARAM[${var}]} ]]; then
475 # echo "strfmt \${STRFMT_PARAM[${var}]}=${STRFMT_PARAM[${var}]}"
476 echo -n${STRFMT_TRANS} "${STRFMT_PARAM[${var}]}"
477 return 0
478 else
479 echo -ne "warn: paramter ${var} is not valid.\n" >&2
480 return
484 ## echo "var=$var"
485 # 参数指定的变量xxx已定义,或xxx未定义,但xxx[]数组有定义,且只包含一个元素
486 if [[ -v "${var}" || $cnt -ge 0 ]]; then
487 # todo:这里需要对输入、输出的变量进行设置。
489 if [[ ${var} =~ "_FMT" ]]; then
490 var=${var%_FMT}
492 if [[ $cnt -ge 1 ]]; then
493 # 不指定数组idx,变量为数组,XXX_FMT[@],输出到XXX[@]
494 for ((; cnt>=0; cnt--)); do
495 ## echo "${var}[$cnt]=\${${var}_FMT[$cnt]}"
496 declare -g ${var}[$cnt]="$(strfmt_p2p < <(eval echo \"\${${var}_FMT[$cnt]}a\"))"
497 eval ${var}[$cnt]="\${${var}[$cnt]:0:-1}"
498 done
499 else
500 # 指定idx的单个数组的元素,XXX_FMT[$i],输出到XXX[$i]
501 # 非数组的元素,XXX_FMT,输出到XXX,即XXX_FMT[0],输出到XXX[0]
502 if [[ -z $array ]]; then
503 eval array="[\${!${var}_FMT[@]}]"
505 ## echo "${var}$array=\${${var}_FMT$array}"
506 declare -g ${var}$array="$(strfmt_p2p < <(eval echo \"\${${var}_FMT$array}a\"))"
507 eval ${var}$array="\${${var}$array:0:-1}"
509 elif [[ ${var} =~ "_fmt" ]]; then
510 var=${var%_fmt}
512 if [[ $cnt -ge 1 ]]; then
513 # 不指定数组idx,变量为数组,XXX_FMT[@],输出到XXX[@]
514 for ((; cnt>=0; cnt--)); do
515 ## echo "${var}[$cnt]=\${${var}_fmt[$cnt]}"
516 declare -g ${var}[$cnt]="$(strfmt_p2p < <(eval echo \"\${${var}_fmt[$cnt]}a\"))"
517 eval ${var}[$cnt]="\${${var}[$cnt]:0:-1}"
518 done
519 else
520 # 指定idx的单个数组的元素,XXX_FMT[$i],输出到XXX[$i]
521 # 非数组的元素,XXX_FMT,输出到XXX,即XXX_FMT[0],输出到XXX[0]
522 if [[ -z $array ]]; then
523 eval array="[\${!${var}_fmt[@]}]"
525 ## echo "${var}$array=\${${var}_fmt[$cnt]}"
526 declare -g ${var}$array="$(strfmt_p2p < <(eval echo \"\${${var}_fmt$array}a\"))"
527 eval ${var}$array="\${${var}${array}:0:-1}"
529 elif [[ -n ${array} ]]; then
530 # $cnt == 0
531 # 指定idx的单个数组的元素,XXX[$i],输出到XXX[0]
532 # xxx: 对于XXX[0],输出到XXX[0],但实际不应这么使用。
533 ## echo "${var}[$array]=\${${var}$array}"
534 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a\"))"
535 eval ${var}[0]="\${${var}[0]:0:-1}"
536 else
537 if [[ ${cnt} == 1 ]]; then
538 # 包含2个元素的数组,且未指定idx
539 if [[ -v ${var}[0] ]]; then
540 # 其中一个idx为0,使用非0的idx值。
541 # xxx: 通常不应该这么使用
542 vname="${var}[@]"
543 eval array=( \${#$var[@]} )
544 array="[${array[1]}]"
545 ## echo "${var}[0]=\${${var}$array}"
546 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a\"))"
547 eval ${var}[0]="\${${var}[0]:0:-1}"
548 else
549 # 两个大于0的idx的元素
550 ### echo "an array var '$var' without index or _fmt or _FMT surfix cannot be used."
551 # 当成普通数组输出
552 eval echo "\${${var}[@]}"
554 elif [[ ${cnt} -gt 1 ]]; then
555 # 包含多个元素的数组,且未指定idx
556 ### echo "an array var '$var' without index or _fmt or _FMT surfix cannot be used."
557 # 当成普通数组输出
558 eval echo "\${${var}[@]}"
559 else
560 # cnt==0
561 # 非数组的元素,XXX,输出到stdout
562 eval array="[\${!${var}[@]}]"
563 if [[ $array == "[0]" ]]; then
564 ## echo "${var} ==> stdout"
565 strfmt_p2p < <(echo "${!var}")
566 else
567 ## echo "${var}[$array]=\${${var}$array}"
568 # xxx: 这里末尾的字符不需要添加,调试用
569 declare -g ${var}[0]="$(strfmt_p2p < <(eval echo \"\${${var}${array}}a\"))"
570 eval ${var}[0]="\${${var}[0]:0:-1}"
574 elif [[ "$(readlink /proc/self/fd/0)" =~ 'pipe:[' ]]; then
575 cat - | strfmt_p2p
576 else
577 echo "no input data or no variable specified."
578 return 1
581 return 0
585 # fsyntax: strfmt_set_domain <domain-str>
586 # fdesc: 设置作用域。作用域字符串以imi和section名称组合。
587 strfmt_set_domain ()
589 local imi="$1"
590 local section=
592 [[ -z $imi ]] && STRFMT_DOMAIN="" && return
593 section="${imi##*:}"
594 imi="${imi%%:*}"
595 STRFMT_DOMAIN="${imi}__${section}_"
596 # echo "strfmt_set_domain($STRFMT_DOMAIN)"
600 # fsyntax: strfmtset <str-var>
601 # fdesc: 设置eval、evaln、trans参数。
602 strfmtset ()
604 if [[ "$2" =~ "en" ]]; then
605 case $1 in
606 eval )
607 STRFMT_EVALN=eval
609 evaln )
610 STRFMT_EVALN=evaln
612 trans )
613 STRFMT_TRANS=e
615 esac
616 elif [[ "$2" =~ "dis" ]]; then
617 case $1 in
618 eval )
619 STRFMT_EVALN=""
621 evaln )
622 STRFMT_EVALN=""
624 trans )
625 STRFMT_TRANS=""
627 esac
632 # $ if [[ "<cataid>" =~ \<([A-Za-z0-9_ ]+)\> ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
633 # $ abc='\<([[:alnum:]]*)\>'; if [[ "<cataid>" =~ $abc ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
635 # $ abc='\<([[:alnum:]]*)\>'; if [[ "<cataid> [type] name \"desc\" [ftype]" =~ \<$abc\>[\ \t]+\[([[:alnum:]]+)*\][\ \t]+([[:alnum:]]+)[\ \t]+\"([[:alnum:]]*)\"[\ \t]+\[([[:alnum:]]*)\].* ]]; then echo xxxxxxxx ${BASH_REMATCH[@]} xxxxxxxx; fi
636 # xxxxxxxx <cataid> [type] name "desc" [ftype] cataid type name desc ftype xxxxxxxx
637 # $ 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
638 # match[0]=<cataid> [type] name "desc" [ftype]
639 # match[1]=cataid
640 # match[2]=type
641 # match[3]=name
642 # match[4]=desc
643 # match[5]=ftype
645 # $ 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
649 # fsyntax: str2var_regexpr <str-var> <fmt-var> <attr-var>
650 # recogonize string with reg-expr.
651 regex_str_dispatch ()
653 local i;
655 if [[ "${1}" =~ $2 ]]; then
656 for ((i=0; i<${#BASH_REMATCH[@]}; i++)); do
657 attr_create ${3}::BASH_REMATCH_${i} = "${BASH_REMATCH[$i]}"
658 done
662 # use string format defined for strfmt.
663 # strrvsfmt "<cataid1> <type1> <name1> <desc1> <ftype1>" "<@{cataid}>\\\ <@{type}>\\\ <@{name}>\\\ <@{desc}>\\\ <@{ftype}>" var
664 strrvsfmt ()
666 local i=0
667 local data
668 local vnamelist=
669 local var_fmt="([[:alnum:]_]+)"
670 local fmt=
672 # dispatch fmt str, and get the var-name list.
673 # echo "aaa=${aaa//@/$'\n'}"
674 # echo "${aaa//@/$'\n'}" | while read data; do echo data=${data}; if [[ "$data" =~ .*\{([[:alnum:]]+)\}.* ]]; then echo MATCH=${BASH_REMATCH[1]}; fi; done
675 while read data; do
676 # echo "data=$data"
677 if [[ "$data" =~ ^\{([[:alnum:]_]+)\} ]]; then
678 # echo "vnamelist[$i]=${BASH_REMATCH[1]}"
679 # echo "data=$var_fmt${data#*\}}"
680 fmt+="$var_fmt${data#*\}}"
681 # echo "fmt=$fmt"
682 vnamelist[$i]="${BASH_REMATCH[1]}"
683 : $(( i++ ))
684 else
685 fmt+="$data"
687 done < <(echo "${2//@/$'\n'}")
689 # reg-expr matching, and fill to the corresponding var under the domain of attr-var paramter given.
690 # try this example string if there is some problem.
691 #[[ "<cataid1> <type1> <name1> <desc1> <ftype1>" =~ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\>\ \<([[:alnum:]_]+)\> ]] && echo XXXXXXXXXXXXXXXXXXXX
692 if [[ "${1}" =~ $fmt ]]; then
693 [[ $(( ${#vnamelist[@]} + 1 )) != ${#BASH_REMATCH[@]} ]] && return
694 for ((i=1; i<${#BASH_REMATCH[@]}; i++)); do
695 echo ${3}::${vnamelist[$(($i - 1))]} = "${BASH_REMATCH[$i]}"
696 # attr_create ${3}::${vnamelist[$i]} = "${BASH_REMATCH[1]}"
697 done
704 # fsyntax: templete <tmpl-file> [output-file]
705 # fdesc: 对templete-file进行var-content-insert。
706 templete ()
708 local output=$2
710 if [[ -z $output || $output == "-" ]]; then
711 cat $1 | strfmt_p2p
712 else
713 cat $1 | strfmt_p2p | $output
717 abc="aaaaaaaaaaaaaa"
718 strfmt_testing ()
720 local fmt="@abc"
721 echo XXXXXXXXXXXXXXXXXXXXXXXXXX
722 strfmt fmt
725 # use reloadshlib strfmt.shlib to load this lib, and open this invoking to debug
726 # code in tesing mode.
727 strfmt_testing
730 ######################
731 # section: file tail
732 ######################