I have a customized .profile that I use in ksh and below is a function that I created to skip back and forth from directories with overly complicated or long names.
我有一个我在ksh中使用的自定义.profile,下面是我创建的一个函数,可以从具有过于复杂或长名称的目录中来回跳过。
As you can see, the pathnames are stored in an array (BOOKMARKS[]
) to keep track of them and reference them at a later time. I want to be able to delete certain values from the array, using a case statement (or OPTARG if necessary) so that I can just type bmk -d #
to remove the path at the associated index.
如您所见,路径名存储在一个数组(BOOKMARKS [])中以跟踪它们并在以后引用它们。我希望能够使用case语句(或必要时的OPTARG)从数组中删除某些值,这样我只需键入bmk -d#即可删除相关索引处的路径。
I have fiddled around with array +A and -A
, but it just wound up screwing up my array (what is left in the commented out code may not be pretty...I didn't proofread it).
我已经摆弄了数组+ A和-A,但它只是搞砸了我的数组(注释掉的代码中剩下的内容可能不太漂亮......我没有校对它)。
Any suggestions/tips on how to create that functionality? Thanks!
有关如何创建该功能的任何建议/提示?谢谢!
# 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
}
3 个解决方案
#1
5
Arrays in the Korn shell (and Bash and others) are sparse, so if you use unset
to delete members of the array, you won't be able to use the size of the array as an index to the last member and other limitations.
Korn shell(以及Bash和其他)中的数组是稀疏的,因此如果使用unset删除数组的成员,则无法使用数组的大小作为最后一个成员的索引和其他限制。
Here are some useful snippets (the second for
loop is something you might be able to put to use right away):
这里有一些有用的片段(第二个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
That last one can eliminate the need for a counter.
最后一个可以消除对计数器的需要。
Here are a couple more handy techniques:
以下是一些更方便的技巧:
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
This all assumes ksh93, some things may not work in earlier versions.
这都假定为ksh93,有些东西可能在早期版本中不起作用。
#2
2
you can use unset. eg to delete array element 1
你可以使用unset。例如,删除数组元素1
unset array[0]
to delete entire array
删除整个数组
unset array
#3
1
A few caveats regarding the previous answer:
关于上一个答案的一些警告:
First: I see this error all the time. When you provide an array element to "unset", you have to quote it. Consider:
第一:我一直看到这个错误。当您提供“unset”数组元素时,您必须引用它。考虑:
$ 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
What happened? Globbing. You obviously wanted to delete element 2 of a[], but shell syntax being what it is, the shell first checked the current directory for a file that matched the glob pattern "a[2]". If it finds a match, it replaces the glob pattern with that filename, and you wind up making a decision about which variable to delete based on what files exist in your current directory.
发生了什么?通配符。你显然想要删除[]的元素2,但shell语法就是这样,shell首先检查当前目录中是否有匹配glob模式“a [2]”的文件。如果找到匹配项,它会用该文件名替换glob模式,最后根据当前目录中存在的文件决定删除哪个变量。
This is profoundly stupid. But it's not something anyone has bothered to fix, apparently, and the error turns up in all kinds of documentation and example code from the last 3 decades.
这是非常愚蠢的。但显然,这并不是任何人都不愿意解决的问题,并且错误在过去30年中出现在所有类型的文档和示例代码中。
Next is a related problem: it's easy to insert elements in your associative array with any key you like. But it's harder to remove these elements:
接下来是一个相关问题:使用您喜欢的任何键在关联数组中插入元素很容易。但是删除这些元素更难:
typeset -A assoc
key="foo] bar"
assoc[$key]=3 #No problem!
unset -v "assoc[$key]" #Problem!
In bash you can do this:
在bash中你可以这样做:
unset -v "assoc[\$key]"
In Korn Shell, you have to do this:
在Korn Shell中,您必须这样做:
unset -v "assoc[foo\]\ bar]"
So it gets a bit more complicated in the case where your keys contain syntax characters.
因此,在密钥包含语法字符的情况下,它会变得更复杂一些。
#1
5
Arrays in the Korn shell (and Bash and others) are sparse, so if you use unset
to delete members of the array, you won't be able to use the size of the array as an index to the last member and other limitations.
Korn shell(以及Bash和其他)中的数组是稀疏的,因此如果使用unset删除数组的成员,则无法使用数组的大小作为最后一个成员的索引和其他限制。
Here are some useful snippets (the second for
loop is something you might be able to put to use right away):
这里有一些有用的片段(第二个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
That last one can eliminate the need for a counter.
最后一个可以消除对计数器的需要。
Here are a couple more handy techniques:
以下是一些更方便的技巧:
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
This all assumes ksh93, some things may not work in earlier versions.
这都假定为ksh93,有些东西可能在早期版本中不起作用。
#2
2
you can use unset. eg to delete array element 1
你可以使用unset。例如,删除数组元素1
unset array[0]
to delete entire array
删除整个数组
unset array
#3
1
A few caveats regarding the previous answer:
关于上一个答案的一些警告:
First: I see this error all the time. When you provide an array element to "unset", you have to quote it. Consider:
第一:我一直看到这个错误。当您提供“unset”数组元素时,您必须引用它。考虑:
$ 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
What happened? Globbing. You obviously wanted to delete element 2 of a[], but shell syntax being what it is, the shell first checked the current directory for a file that matched the glob pattern "a[2]". If it finds a match, it replaces the glob pattern with that filename, and you wind up making a decision about which variable to delete based on what files exist in your current directory.
发生了什么?通配符。你显然想要删除[]的元素2,但shell语法就是这样,shell首先检查当前目录中是否有匹配glob模式“a [2]”的文件。如果找到匹配项,它会用该文件名替换glob模式,最后根据当前目录中存在的文件决定删除哪个变量。
This is profoundly stupid. But it's not something anyone has bothered to fix, apparently, and the error turns up in all kinds of documentation and example code from the last 3 decades.
这是非常愚蠢的。但显然,这并不是任何人都不愿意解决的问题,并且错误在过去30年中出现在所有类型的文档和示例代码中。
Next is a related problem: it's easy to insert elements in your associative array with any key you like. But it's harder to remove these elements:
接下来是一个相关问题:使用您喜欢的任何键在关联数组中插入元素很容易。但是删除这些元素更难:
typeset -A assoc
key="foo] bar"
assoc[$key]=3 #No problem!
unset -v "assoc[$key]" #Problem!
In bash you can do this:
在bash中你可以这样做:
unset -v "assoc[\$key]"
In Korn Shell, you have to do this:
在Korn Shell中,您必须这样做:
unset -v "assoc[foo\]\ bar]"
So it gets a bit more complicated in the case where your keys contain syntax characters.
因此,在密钥包含语法字符的情况下,它会变得更复杂一些。