来自外部文件的Bash菜单

时间:2016-12-15 14:12:09

标签: arrays bash macos

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

这是什么

使用rsync上传/下载文件的脚本。 该脚本将获取最新的配置/菜单'来自远程服务器。该文件 menu.txt 将创建一个列出项目的菜单,选择后即可获得下载/上传选项。

问题

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

更多信息:create_menus功能

此函数解析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&#34; $ {MENU_MAIN [@]}&#34;

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&gt; function create_menus()&gt;这应该基于menu.txt文件创建一个菜单。

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

1 个答案:

答案 0 :(得分: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-appends $newElement$arr第一个元素(!)的值,没有添加新的。
      • arr=( 1 2 ); arr+=3; declare -p arr - &gt; declare -a arr='([0]="13" [1]="2")'
  • 无法使用arrCopy=( $arr ) 复制整个数组 - 所有这一切都是为了创建仅包含$arr第一个元素。要引用数组作为整体,您必须使用 "${arr[@]}" (括在"..."中确保不应用任何分词):< / p>

    • arrCopy=( "${arr[@]}" ) - 确定
    • arrCopy=( $arr ) - BROKEN - 仅复制第一个元素

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