来自外部文件的Bash菜单

问题描述 投票:1回答:1

不知道在哪里寻求帮助所以在这里尝试。我正在创建一个带有一些操作的bash菜单脚本并阅读大量的bash教程,但认为我的大脑开始融化所有不同的语法和方法,无法完全包围bash / sh。结束脚本将在OSX上为艺术团队运行。

What this is

使用rsync上载/下载文件的脚本。该脚本将从远程服务器获取最新的“配置/菜单”。该文件menu.txt将创建一个列出项目的菜单,当您选择时,您可以选择下载/上传。

Issue

我遇到的问题是如何处理菜单中的数组。试过没有运气的2d阵列所以现在它分成3个数组来保存我需要的值。但是,当试图显示菜单时,我无法使其正常工作。查看底部,了解如何测试,显示什么以及应该显示什么。

more info: create_menus function

此函数解析menu.txt以构建显示菜单时使用的数组,

Project Title5, source1dir, destination1dir
Project Title6, source2dir, destination2dir
Project Title7, source3dir, destination3dir

而不是选择1'项目标题5'将显示菜单

1) Project
2) Title5Project
3) Title6Project
4) Title7Quit

脚本:

function create_menus() {
    #operations for project
    MENU_OPERATIONS=(
      "Get latest from remote"
      "Show changes from remote"
      "Send latest from me to remote"
      "Show changes from me to remote"
      "Return to main menu"
  )
    #projects to choose from, load from textfile
    declare -a t; declare -a s; declare -a d;
    while IFS= read -r line; do
        IFS=',' read -ra obj <<< "$line"
        #TODO 2d array nicer than 3 arrays!
        eval "t+=\"${obj[0]}\""
        eval "s+=\"${obj[1]}\""
        eval "d+=\"${obj[2]}\""
    done <$FILE_MENU
    t+="Quit" #add quit
    MENU_MAIN=($t)
    PROJECT_SOURCE=($s)
    PROJECT_TARGET=($d)
}

然后显示主菜单main_menu“$ {MENU_MAIN [@]}”

function main_menu
{
    #clear
    #header
    PS3="Select project: "
    select option; do # in "$@" is the default
        if [ "$REPLY" -eq "$#" ];
        then
            echo "Exiting..."
            break;
        elif [ 1 -le "$REPLY" ] && [ "$REPLY" -le $(($#-1)) ];
        then
            # $REPLY = index
            # $option = text
            echo "You selected $option which is option $REPLY"
            SELETED_PROJECT_TITLE=${MENU_MAIN[$REPLY]}
            SELETED_PROJECT_SOURCE=${PROJECT_SOURCE[$REPLY]}
            SELETED_PROJECT_TARGET=${PROJECT_TARGET[$REPLY]}
            echo "Sel title $SELETED_PROJECT_TITLE"
            echo "Sel source $SELETED_PROJECT_SOURCE"
            echo "Sel target $SELETED_PROJECT_TARGET"
            project_menu "${MENU_OPERATIONS[@]}" "$SELETED_PROJECT_TITLE" "$SELETED_PROJECT_SOURCE" "$SELETED_PROJECT_TARGET"
            break;
        else
            echo "Incorrect Input: Select a number 1-$#"
        fi
    done
}

这是完整的代码https://github.com/fbacker/BigFileProjectsSync/blob/master/app.sh

添加更多说明

去测试:

git clone https://github.com/fbacker/BigFileProjectsSync.git
cd BigFileProjectsSync/
./app.sh

怎么了:

Shows a menu with options:
1) Project
2) Title5Project
3) Title6Project
4) Title7Quit

应该发生:

Shows a menu with options:
1) Project Title5
2) Project Title6
3) Project Title7
4) Quit

app.sh> function create_menus()>这应该基于menu.txt文件创建一个菜单。

menu.txt一行是一个项目:第一个值是项目名称,第二个值是源目录,第三个是目标目录。

arrays bash macos
1个回答
1
投票

这是你的create_menus()函数的固定版本,应该可以解决这个问题:

function create_menus() {

    #operations for project
    # MENU_OPERATIONS=( # ... OMITTED FOR BREVITY

    #projects to choose from
    local -a titles sources destinations
    local title source destination
    while IFS='|' read -r title source destination; do
        titles+=( "$title" )
        sources+=( "$source" )
        destinations+=( "$destination" )
    done < <(sed 's/, /|/g' "$FILE_MENU")

    # Copy to global arrays
    MENU_MAIN+=( "${titles[@]}" )
    PROJECT_SOURCE+=( "${sources[@]}" )
    PROJECT_TARGET+=( "${destinations[@]}" )

    MENU_MAIN+=( "Quit" ) #add quit
}

你的方法有两个关键问题(我假设下面有一个数组变量$arr):

  • 为了将新元素附加到数组,新元素本身也必须指定为数组;即,它必须用(...)括起来: arr+=( "$newElement" ) - 好的:值作为新元素附加 arr+=$newElement - BROKEN:String-将$newElement的值附加到$arr的第一个元素(!),而不添加新元素。 arr=( 1 2 ); arr+=3; declare -p arr - > declare -a arr='([0]="13" [1]="2")'
  • 你不能用arrCopy=( $arr )复制整个数组 - 所有这一切都是为了创建一个只包含$arr第一个元素的单项数组。要将数组作为一个整体引用,必须使用"${arr[@]}"(封装在"..."中确保不应用任何分词): arrCopy=( "${arr[@]}" ) - 好的 arrCopy=( $arr ) - BROKEN - 仅复制第一个元素

另请注意,最好不要使用全大写的shell变量名来为avoid conflicts with environment variables and special shell variables


© www.soinside.com 2019 - 2024. All rights reserved.