簡體   English   中英

從ksh中的數組中刪除特定值

[英]Deleting specific values from an array in ksh

我有一個我在ksh中使用的自定義.profile,下面是我創建的一個函數,可以從具有過於復雜或長名稱的目錄中來回跳過。

如您所見,路徑名存儲在一個數組( 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
}

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,有些東西可能在早期版本中不起作用。

你可以使用unset。 例如,刪除數組元素1

unset array[0]

刪除整個數組

unset array

關於上一個答案的一些警告:

第一:我一直看到這個錯誤。 當您提供“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

發生了什么? 通配符。 你顯然想要刪除[]的元素2,但shell語法就是這樣,shell首先檢查當前目錄中是否有與glob模式 “a [2]”匹配的文件。 如果找到匹配項,它會用該文件名替換glob模式,最后根據當前目錄中存在的文件決定刪除哪個變量。

這是非常愚蠢的。 但顯然,這並不是任何人都不願意解決的問題,並且在過去的三十年里,各種文檔和示例代碼中的錯誤都出現了。

接下來是一個相關問題:使用您喜歡的任何鍵在關聯數組中插入元素很容易。 但是刪除這些元素更難:

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]"

因此,在密鑰包含語法字符的情況下,它會變得更復雜一些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM