文章目录
问题描述:
用bash shell 实现posh_d +n 以及 pop_d +n功能,具体要求:
- 能处理包含空格的目录
- 不能用上面例子的实现方式
- 不能用awk等其他工具或者直接调用系统的push_d 及pop_d
实现思路:
-
使用数组实现目录栈,数组从下标0开始使用,数组长度-1的为栈顶,下标0的为栈底。
-
push_d() 将可能参数划分为四种情况,并用flag变量记录,函数默认只有一个参数,将所有参数看成一个字符串($*)
**push_d +n** 将位置为 n (从栈顶目录开始数第n个) 的目录移至栈顶,其他目录下移,并 cd 至栈顶目录。 参数n不能为负数或越界。 **push_d dir** cd 至dir目录,并将当前目录压栈。 第一次调用需将当前目录压栈,再 cd 至 dir 目录,并将 cd 后的目录压栈。 需判断目录合法性,存在。下面代码不能处理名为 “+3” 这样的类似的目录。
push_d
若当前数组中存在两个目录,交换栈顶目录和次栈顶目录位置,并 cd 至栈顶目录
- pop_d() 将可能参数划分为四种情况,并用flag变量记录,函数默认只有一个参数,将所有参数看成一个字符串($*)
pop_d +n
将位置为 n (从栈顶目录开始数第n个) 的目录删除,其他目录下移。
如参数为1,即删除的为栈顶目录,则 cd 至新栈顶目录。
参数n不能为负数或越界。
pop_d
若目录栈中存在两个以上目录,删除栈顶目录,并 cd 至 新栈顶目录
存在一个目录,清空目录栈
不存在目录,报错
- outDirArray()输出目录栈中目录,以回车分隔
实现代码:
#!bin/bash
push_d()
{
#获取目录数组大小
len=${#DIR_ARRAY[@]}
#将所有参数提取为一个字符串
param=$*
k=${param#+}
#flag 记录参数四种情况
#flag=0 ----不带参数 push_d
#flag=1 ----+数字参数,且没有越界 push_d +n
#flag=2 ----带目录参数,可能是非法或不存在的 push_d dir
#flag=3 ----数字参数越界
if [ -z "${param}" ]; then
#参数为空
flag=0
elif [ -n "$k" -a "$k" == "${k//[^0-9]/}" ]; then
if ((k <= len)); then
#正常数字参数
flag=1
else
#数字参数越界
flag=3
fi
else
#字符串参数
flag=2
fi
case ${flag} in
0)
#若存在两个目录,交换栈顶目录和次栈顶目录位置,并 cd 至栈顶目录
if ((len>=2));then
index=$((len-1)) #栈顶目录下标
temp=${DIR_ARRAY[index]}
DIR_ARRAY[index]=${DIR_ARRAY[$((index-1))]}
DIR_ARRAY[$((index-1))]=${temp}
cd ${DIR_ARRAY[index]}
outDirArray
#栈中不存在两目录
else
echo "error:Two directories do not exist in the stack!"
fi
;;
1)
#将位置为 k (从栈顶目录开始数第k个) 的目录移至栈顶,并 cd 至该目录
temp=${DIR_ARRAY[$((len-k))]}
for((i=len-k;i<len-1;i++))
do
DIR_ARRAY[i]=${DIR_ARRAY[i+1]}
done
DIR_ARRAY[$((len-1))]=${temp}
cd ${DIR_ARRAY[$((len-1))]}
outDirArray
;;
2)
#pushd的功能,将目录压栈并cd至该目录
dir=$param
#如果栈空(数组空) 第一次使用push_d情况
if ((len==0)); then
if [ -d "${dir}" ]; then #判断目录是否存在
DIR_ARRAY[0]=$(pwd)
DIR_ARRAY[1]=$(pwd)"/"${dir}
outDirArray
cd "${dir}"
else
echo "error:directory does not exist or error!"
fi
elif [ -d "${dir}" ]; then #判断目录是否存在
cd "${dir}"
DIR_ARRAY[$((len))]=$(pwd)
outDirArray
else
echo "error:directory does not exist or error!"
fi
;;
3)
echo "error:Parameter out of bounds!"
;;
*) echo "error"
esac
}
pop_d()
{
len=${#DIR_ARRAY[@]} #获取目录数组大小
param=$*
k=${param#+}
#flag 记录参数四种情况
#flag=0 ----不带参数 pop_d
#flag=1 ----+数字参数,且没有越界 pop_d +n
#flag=2 ----数字参数越界
#flag=3 ----参数语法错误
if [ -z "${param}" ]; then
#参数为空
flag=0
elif [ -n "$k" -a "$k" == "${k//[^0-9]/}" ]; then
if ((k <= len)); then
#正常数字参数
flag=1
else
#数字参数越界
flag=2
fi
else
#字符串参数
flag=3
fi
case ${flag} in
0)
#若目录栈大于1,删除当前栈顶目录,并 cd 至删除后栈顶目录
if ((len>1));then
index=$((len-1)) #栈顶目录下标
unset DIR_ARRAY[index]
index=$((index-1))
cd ${DIR_ARRAY[index]}
outDirArray
#栈中目录等于1
elif ((len==1));then
unset DIR_ARRAY[0]
outDirArray
else
echo "error:Two directories do not exist in the stack!"
fi
;;
1)
#将位置为 k (从栈顶目录开始数第k个) 的目录删除,如果删除的为栈顶目录(k=1),则cd 至下一栈顶目录
if ((k==1));then
{
unset DIR_ARRAY[$((len-1))]
cd ${DIR_ARRAY[$((len-2))]}
outDirArray
}
else
for((i=len-k;i<len-1;i++))
do
DIR_ARRAY[i]=${DIR_ARRAY[i+1]}
done
unset DIR_ARRAY[$((len-1))]
outDirArray
fi
;;
2)
echo "error:Parameter out of bounds!"
;;
3)
echo "error:Parameter error!"
;;
*) echo "error"
esac
}
#输出DIR_ARRAY 栈顶目录在数组元素最后 模仿pushd 逆序输出目录
outDirArray()
{
len=${#DIR_ARRAY[@]}
echo
for((i=len-1;i>=0;i--))
do
echo ${DIR_ARRAY[i]}" "
done
echo
}