linux sh : user array as function's input or output parameter
发布日期:2021-06-30 22:17:02 浏览次数:2 分类:技术文章

本文共 15260 字,大约阅读时间需要 50 分钟。

前言

看了一段书,讲到了用数组作为脚本函数的入参和出参,正好是我有需求的地方。

前面做的实验,暂时不知道怎么传出多个参数,就每个函数配发了专用的全局变量(有几个出参就配发函数专用的几个全局变量),这样写维护不方便,丑陋。

将前面的一个实验(功能是全的),将全局变量换成数组。 搞了2天,细节蛮多,改的不对,结果不对了。调试了很久。可以用bash -x my.sh, 来调试,也不方便。还是要将基础函数测试过,然后搭积木,可维护性高。如果有错误,用echo来打印调试语句,配合read 暂停程序,来的实在。

如果sh大了,有个几千行,那调试过程就繁琐了。如果有像gdb那样能单步调试脚本的调试器就好了。

#   if need pause sh, do below #   local c_tmp='' #   read -n1 c_tmp

for 循环是依赖IFS的,在for的上面保存旧IFS, 设置新IFS,等for循环结束后,恢复IFS。今天调试时,有一个bug,是由IFS引起的。

实验

# !/bin/bash# @file demo_004.sh# @brief wrap a shell script functin to check user exist, #   use array to pass output parameter, not use any global var# run result# --------------------------------------------------------------------------------# | @file   demo_004.sh# | @brief  wrap a shell script functin to check user exist# |     use array to pass output parameter, not use any global var# --------------------------------------------------------------------------------# | check user exist# | 1.0.0.4# | 2018-02-12 14:45# --------------------------------------------------------------------------------# | 2018_02_13_05_13_10# | /bin/bash# | zh_CN.UTF-8# | root# --------------------------------------------------------------------------------# user [root] exist, user home dir = [/root])## user [dev] not exist, but have home dir, user home dir = [/home/dev]## user [user_not_exist] not exist## --------------------------------------------------------------------------------# | END# --------------------------------------------------------------------------------# --------------------------------------------------------------------------------# define macro# --------------------------------------------------------------------------------# run time env is debian7.5PROG_NAME="check user exist"PROG_VER="1.0.0.4"PROG_TIME="2018-02-12 14:45"IND_CHAR=-LINE10=${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}LINE80=${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}WALL_CHAR='|'# --------------------------------------------------------------------------------# global value# --------------------------------------------------------------------------------## err code define#G_ERR_CODE_BASE=0G_ERR_CODE_OK=$(echo "scale=4; $G_ERR_CODE_BASE + 0" | bc)G_ERR_CODE_ERR=$(echo "scale=4; $G_ERR_CODE_BASE + 1" | bc)G_ERR_CODE_USER_NOT_EXIST=$(echo "scale=4; $G_ERR_CODE_BASE + 2" | bc)G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR=$(echo "scale=4; $G_ERR_CODE_BASE + 3" | bc)# row info below# games:x:5:60:games:/usr/games:/bin/sh# one row have 7 fields, indicate char is ':'# field 0 is username# field 5 is home dir#g_etc_passwd_row_field_index_user_name=0g_etc_passwd_row_field_index_home_dir=5# --------------------------------------------------------------------------------# init# --------------------------------------------------------------------------------function func_init() {    local i_index=0    clear    # print 25 empty lines for run result    for (( i_index=0; i_index < 25; i_index++ ))    do        echo    done}# --------------------------------------------------------------------------------# uinit# --------------------------------------------------------------------------------function func_uinit() {    exit 0}# --------------------------------------------------------------------------------# show title# --------------------------------------------------------------------------------function func_show_title() {    echo -e "${LINE80}"    echo -e -n "${WALL_CHAR}"    echo -e "\t@file\tdemo_004.sh"    echo -e -n "${WALL_CHAR}"    echo -e "\t@brief\twrap a shell script functin to check user exist"    echo -e -n "${WALL_CHAR}"    echo -e "\t\tuse array to pass output parameter, not use any global var"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# show tail# --------------------------------------------------------------------------------function func_show_tail() {    echo -e "${LINE80}"    echo -e -n "${WALL_CHAR}"    echo -e "\tEND"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# show os info# --------------------------------------------------------------------------------function func_show_os_info() {    local str_date=$(date +%Y_%m_%d_%H_%M_%S)    # show time    echo -e -n "${WALL_CHAR}"    echo -e "\t${str_date}"    # show shell    echo -e -n "${WALL_CHAR}"    echo -e "\t${SHELL}"    # show language    echo -e -n "${WALL_CHAR}"    echo -e "\t${LANG}"    # show user    echo -e -n "${WALL_CHAR}"    echo -e "\t${USER}"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# show prog info# --------------------------------------------------------------------------------function func_show_prog_info() {    # show prog name    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_NAME}"    # show prog version    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_VER}"    # show code modify time    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_TIME}"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# @fn func_show_ary()# @param IN array name# @param IN array self# --------------------------------------------------------------------------------function func_show_ary() {    local array_in=""    local ary_item=""    local i_index=0    local i_index_to_disp=0    array_in=$@    IFS_org=$IFS    IFS=$' '    for ary_item in $array_in    do        # skip $1, this is array name        if [ $i_index -ne 0 ]        then            echo "$1[$i_index_to_disp] = $ary_item"            i_index_to_disp=$(echo "scale=4; $i_index_to_disp + 1" | bc)        fi        i_index=$(echo "scale=4; $i_index + 1" | bc)    done    IFS=$IFS_org    echo}# --------------------------------------------------------------------------------# @fn func_get_ary_by_index()# @brief the all array is {index_obj, ary[0], ary[1], ary[2], ...}# @param IN array index, index base 0, if index is 0, return ary[0], not return index_obj# @param IN array self# @return ary[i]# --------------------------------------------------------------------------------function func_get_ary_by_index() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local array_in=""    local ary_item=""    local i_index=0    local i_index_obj=$1    array_in=$@    i_index_obj=$(echo "scale=4; $i_index_obj + 1" | bc)    i_index=0    IFS_org=$IFS    IFS=$' '    for ary_item in $array_in    do        if [ $i_index -eq 0 ]        then            # $1 is the obj index            i_index_obj=$ary_item            i_index_obj=$(echo "scale=4; $i_index_obj + 1" | bc)            elif [ $i_index -eq $i_index_obj ]        then            echo "$ary_item"            break        fi        i_index=$(echo "scale=4; $i_index + 1" | bc)    done    IFS=$IFS_org    return 0}# --------------------------------------------------------------------------------# @fn func_get_user_name_and_home_dir_for_one_row_from_etc_passwd# @brief get usrname and homedir from one row from /etc/passwd# @parameter IN, $1, row content# @parameter OUT, array ary_to_return, #   ary_to_return[0] = arysize, #   ary_to_return[1] is rc, #   ary_to_return[2] is username, #   ary_to_return[3] = home dir# @return G_ERR_CODE_OK or G_ERR_CODE_ERR# --------------------------------------------------------------------------------function func_get_user_name_and_home_dir_for_one_row_from_etc_passwd() {    local ary_to_return    local rc=$G_ERR_CODE_ERR    local str_user_name=""    local str_home_dir=""    local str_field=""    local IFS_org=""    local pos=0    local b_was_get_user_name=false    local b_was_get_home_dir=false    IFS_org=$IFS    IFS=$':'    for str_field in $1    do        if [ $pos -eq $g_etc_passwd_row_field_index_user_name ]        then            b_was_get_user_name=true            str_user_name=$str_field        elif [ $pos -eq $g_etc_passwd_row_field_index_home_dir ]        then            b_was_get_home_dir=true            str_home_dir=$str_field        fi        pos=$(echo "scale=4; $pos + 1" | bc) # pos++        if [ "$b_was_get_home_dir" = true ] && [ "$b_was_get_home_dir" = true ]        then            rc=$G_ERR_CODE_OK            break        fi    done    IFS=$IFS_org    # fill output parameter    ary_to_return[0]=3    ary_to_return[1]=$rc    ary_to_return[2]=$str_user_name    ary_to_return[3]=$str_home_dir    echo ${ary_to_return[*]} # this is all array content    return $rc}# --------------------------------------------------------------------------------# @fn func_case_gen_ary# @brief gen ary[4] to test# @prarmeter OUT, ary_to_return#   ary_to_return[0] = ary size#   ary_to_return[1] = return code#   ary_to_return[2] = user name#   ary_to_return[3] = home dir# @return g_err_code_xx# --------------------------------------------------------------------------------function func_case_gen_ary() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local rc=$G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR    local ary_to_return    ary_to_return[0]=3    ary_to_return[1]=$rc    ary_to_return[2]="user_name"    ary_to_return[3]="user_home_dir"    echo ${ary_to_return[*]} # this is all array content    return $rc}# --------------------------------------------------------------------------------# @fn func_is_user_exist# @brief is user exist# @parameter IN, username# @prarmeter OUT, ary_to_return#   ary_to_return[0] = ary size#   ary_to_return[1] = return code#   ary_to_return[2] = user name#   ary_to_return[3] = home dir# @return g_err_code_xx# --------------------------------------------------------------------------------function func_is_user_exist() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local ary_to_return    local rc=$G_ERR_CODE_ERR    local str_user_name=""    local str_user_home=""    local str_user_name_rv=""    local IFS_org=""    local str_row_content=""    local str_user_home_rv=""    local rc_tmp_ary    local rc_tmp=0    # user name    str_user_name=$1    # user home     str_user_home="/home/${str_user_name}"    IFS_org=$IFS    IFS=$'\n'    for str_row_content in $(cat "/etc/passwd")    do        rc_tmp_ary=$(func_get_user_name_and_home_dir_for_one_row_from_etc_passwd $str_row_content)        # rc_tmp_ary = 4 0 speech-dispatcher /var/run/speech-dispatcher        rc_tmp=$?        str_user_name_rv=$(func_get_ary_by_index 2 $rc_tmp_ary)        str_user_home_rv=$(func_get_ary_by_index 3 $rc_tmp_ary)        if [ $rc_tmp -eq $G_ERR_CODE_ERR ]        then            continue        elif [ "$str_user_name" = "$str_user_name_rv" ]        then            # ok : on rc_tmp_ary, can get username and homedir            rc=$G_ERR_CODE_OK            break;        fi    done    IFS=$IFS_org    if [ $rc -eq $G_ERR_CODE_OK ]    then        # find user in /etc/passwd        # set rc, fill ary and echo ary, then to return        ary_to_return[0]=3 # parameter counter(3 = $G_ERR_CODE_OK + user_name + user_home_dir)        ary_to_return[1]=$rc # reture code        ary_to_return[2]=$str_user_name_rv # user name        ary_to_return[3]=$str_user_home_rv # user home dir        echo ${ary_to_return[*]} # this is all array content        return $rc    fi    # if user name not in /etc/passwd, try to find is the user have home dir ?    # before opt a file, please check is file exist. if file is dir, do check also    # do check can guard some error message on opt file    if ! [ -d $str_user_home ]    then        rc=$G_ERR_CODE_USER_NOT_EXIST        # fill output parameter        ary_to_return[0]=3        ary_to_return[1]=$rc        ary_to_return[2]=$str_user_name        ary_to_return[3]=""        echo ${ary_to_return[*]}        return $rc    fi    # ls -d xx # only list dir by give    str_user_name_rv=$str_user_name    str_user_home_rv=$(ls -d $str_user_home) # e.g. return /home/root    rc_tmp=$? #e.g. return 0, 1, or other int value    # if dir not exist, rc_tmp = 2    # rc_tmp is number, cmpare use -eq    if [ 0 -eq $rc_tmp ]    then        str_user_home_rv=$str_user_home        rc=${G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR}    else        str_user_home_rv=""        rc=${G_ERR_CODE_USER_NOT_EXIST}    fi    # fill ary and echo ary, set rc to return    ary_to_return[0]=3     ary_to_return[1]=$rc     ary_to_return[2]=$str_user_name_rv    ary_to_return[3]=$str_user_home_rv    echo ${ary_to_return[*]} # this is all array content    return $rc}# --------------------------------------------------------------------------------# fuc_show_user_info# --------------------------------------------------------------------------------function fuc_show_user_info() {    local ary_to_return    local rc=0    local i_index=0    local ary_val=""    local str_user_name=""    local str_user_home=""    # $1 is user name    ary_to_return=$(func_is_user_exist $1)    rc=$?    # func_show_ary "ary_to_return" $ary_to_return    if [ $rc -eq $G_ERR_CODE_OK ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        str_user_home=$(func_get_ary_by_index 3 $ary_to_return)        echo "user [$str_user_name] exist, user home dir = [$str_user_home])"    elif [ $rc -eq $G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        str_user_home=$(func_get_ary_by_index 3 $ary_to_return)        echo "user [$str_user_name] not exist, but have home dir, user home dir = [$str_user_home]"    elif [ $rc -eq $G_ERR_CODE_USER_NOT_EXIST ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        echo "user [$str_user_name] not exist"    else        echo "unknow return code, please contact admin"    fi    echo}# --------------------------------------------------------------------------------# do task# --------------------------------------------------------------------------------function func_do_task() {    # test user exist and have home dir    fuc_show_user_info "root"    # user not exist, but have home dir    fuc_show_user_info "dev"    # user not exist and have not home dir    fuc_show_user_info "user_not_exist"}# --------------------------------------------------------------------------------# save some test case# --------------------------------------------------------------------------------function func_test_case() {    # test : gen ary    ary_to_return=$(func_case_gen_ary)    rc=$?    # test : show ary    func_show_ary "ary_to_return" $ary_to_return    # test : func_get_ary_by_index, index base 0    str_rv=$(func_get_ary_by_index 0 $ary_to_return)    echo "str_rv = $str_rv"    func_get_ary_by_index 1 $ary_to_return    func_get_ary_by_index 2 $ary_to_return    ary_element_3=$(func_get_ary_by_index 3 $ary_to_return)    echo "ary_to_return[3] = $ary_element_3"}# --------------------------------------------------------------------------------# main shell script# --------------------------------------------------------------------------------func_initfunc_show_titlefunc_show_prog_infofunc_show_os_info# func_test_casefunc_do_taskfunc_show_tailfunc_uinit

转载地址:https://lostspeed.blog.csdn.net/article/details/79322236 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:linux sh : use local shell script library
下一篇:linux sh : read user input

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月10日 19时42分35秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章