我有一个自定义的.profile,我在ksh中使用,下面是我创建的一个函数,可以从具有过于复杂或长名称的目录中来回跳过。
如您所见,路径名存储在一个数组(BOOKMARKS[]
)中,以便跟踪它们并在以后引用它们。我希望能够使用case语句(或必要时的OPTARG)从数组中删除某些值,这样我只需键入bmk -d #
即可删除相关索引处的路径。
我已经摆弄了array +A and -A
,但它刚刚搞砸了我的阵列(注释掉的代码中剩下的内容可能并不漂亮......我没有校对它)。
有关如何创建该功能的任何建议/提示?谢谢!
# To bookmark the current directory you are in for easy navigation back and forth from multiple non-aliased directories
# Use like 'bmk' (sets the current directory to a bookmark number) to go back to this directory, i.e. type 'bmk 3' (for the 3rd)
# To find out what directories are linked to which numbers, type 'bmk -l' (lowercase L)
# For every new directory bookmarked, the number will increase so the first time you run 'bmk' it will be 1 then 2,3,4...etc. for every consecutive run therea
fter
# TODO: finish -d (delete bookmark entry) function
make_bookmark()
{
if [[ $# -eq 0 ]]; then
BOOKMARKS[${COUNTER}]=${PWD}
(( COUNTER=COUNTER+1 ))
else
case $1 in
-l) NUM_OF_ELEMENTS=${#BOOKMARKS[*]}
while [[ ${COUNTER} -lt ${NUM_OF_ELEMENTS} ]]
do
(( ACTUAL_NUM=i+1 ))
echo ${ACTUAL_NUM}":"${BOOKMARKS[${i}]}
(( COUNTER=COUNTER+1 ))
done
break ;;
#-d) ACTUAL_NUM=$2
#(( REMOVE=${ACTUAL_NUM}-1 ))
#echo "Removing path ${BOOKMARKS[${REMOVE}]} from 'bmk'..."
#NUM_OF_ELEMENTS=${#BOOKMARKS[*]}
#while [[ ${NUM_OF_ELEMENTS} -gt 0 ]]
#do
#if [[ ${NUM_OF_ELEMENTS} -ne ${ACTUAL_NUM} ]]; then
# TEMP_ARR=$(echo "${BOOKMARKS[*]}")
# (( NUM_OF_ELEMENTS=${NUM_OF_ELEMENTS}-1 ))
#fi
#echo $TEMP_ARR
#done
#break
#for VALUE in ${TEMP_ARR}
#do
# set +A BOOKMARK ${TEMP_ARR}
#done
#echo ${BOOKMARK[*]}
#break ;;
*) (( INDEX=$1-1 ))
cd ${BOOKMARKS[${INDEX}]}
break ;;
esac
fi
}
答案 0 :(得分:5)
Korn shell(和Bash等)中的数组很稀疏,因此如果使用unset
删除数组成员,则无法使用数组的大小作为索引最后一个成员和其他限制。
以下是一些有用的代码段(第二个for
循环是您可以立即使用的内容):
array=(1 2 3)
unset array[2]
echo ${array[2]} # null
indices=(${!array[@]}) # create an array of the indices of "array"
size=${#indices[@]} # the size of "array" is the number of indices into it
size=${#array[@]} # same
echo ${array[@]: -1} # you can use slices to get array elements, -1 is the last one, etc.
for element in ${array[@]}; do # iterate over the array without an index
for index in ${indices[@]} # iterate over the array WITH an index
do
echo "Index: ${index}, Element: ${array[index]}"
done
for index in ${!array[@]} # iterate over the array WITH an index, directly
最后一个可以消除对计数器的需要。
以下是一些更方便的技巧:
array+=("new element") # append a new element without referring to an index
((counter++)) # shorter than ((counter=counter+1)) or ((counter+=1))
if [[ $var == 3 ]] # you can use the more "natural" comparison operators inside double square brackets
while [[ $var < 11 ]] # another example
echo ${array[${index}-1] # math inside an array subscript
这一切都假定为ksh93,有些东西在早期版本中可能不起作用。
答案 1 :(得分:2)
你可以使用unset。例如,删除数组元素1
unset array[0]
删除整个数组
unset array
答案 2 :(得分:1)
关于上一个答案的一些警告:
首先:我一直看到这个错误。当你提供一个数组元素&#34; unset&#34;,你必须引用它。考虑:
$ echo foo > ./a2
$ ls a[2]
a2
$ a2="Do not delete this"
$ a=(this is not an array)
$ unset -v a[2]
$ echo "a2=${a2-UNSET}, a[]=${a[@]}"
a2=UNSET a[]=this is not an array
发生什么事了?通配符。你显然想要删除[]的元素2,但shell语法就是这样,shell首先检查当前目录中是否有与 glob模式匹配的文件&#34; a [2] &#34 ;.如果找到匹配项,它会用该文件名替换glob模式,最后根据当前目录中存在的文件决定删除哪个变量。
这是非常愚蠢的。但是,显然,并不是任何人都不愿意解决的问题,并且错误在过去30年中出现在所有类型的文档和示例代码中。
接下来是一个相关问题:使用您喜欢的任何键在关联数组中插入元素很容易。但是删除这些元素更难:
typeset -A assoc
key="foo] bar"
assoc[$key]=3 #No problem!
unset -v "assoc[$key]" #Problem!
在bash中你可以这样做:
unset -v "assoc[\$key]"
在Korn Shell中,你必须这样做:
unset -v "assoc[foo\]\ bar]"
因此,在您的密钥包含语法字符的情况下,它会变得更复杂。