不知道在哪里寻求帮助,所以在这里尝试。 我正在创建一个包含一些操作的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&#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一行是一个项目:第一个值是项目名称,第二个值是源目录,第三个是目标目录。
答案 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。