不知道在哪里寻求帮助所以在这里尝试。我正在创建一个带有一些操作的bash菜单脚本并阅读大量的bash教程,但认为我的大脑开始融化所有不同的语法和方法,无法完全包围bash / sh。结束脚本将在OSX上为艺术团队运行。
使用rsync上载/下载文件的脚本。该脚本将从远程服务器获取最新的“配置/菜单”。该文件menu.txt将创建一个列出项目的菜单,当您选择时,您可以选择下载/上传。
我遇到的问题是如何处理菜单中的数组。试过没有运气的2d阵列所以现在它分成3个数组来保存我需要的值。但是,当试图显示菜单时,我无法使其正常工作。查看底部,了解如何测试,显示什么以及应该显示什么。
此函数解析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一行是一个项目:第一个值是项目名称,第二个值是源目录,第三个是目标目录。
这是你的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。