Làm thế nào tôi có thể loại bỏ hoàn toàn một phần tử khỏi một mảng?


48

unset array[0]loại bỏ phần tử nhưng nếu tôi làm thì echo ${array[0]}tôi nhận được giá trị null, ngoài ra còn có các cách khác để làm điều này nhưng nếu một phần tử của mảng chứa khoảng trắng như bên dưới

array[0]='james young'
array[1]='mary'
array[2]='randy orton'

nhưng những điều này cũng không thực hiện được công việc

array=${array[@]:1} #removed the 1st element

bây giờ tôi muốn mảng mới giống như

array[0]='mary'
array[1]='randy orton'

Các khoảng trắng gây ra sự cố sau khi gán và mảng thực tế trở nên giống như thay thế.

array=(mary randy orton)

4
Không, không phải là không gian gây rắc rối, nhưng thiếu trích dẫn.
manatwork 18/03/13

Câu trả lời:


68

Chỉ cần sử dụng cú pháp mảng trên bài tập và trích dẫn biến của bạn:

array=("${array[@]:1}") #removed the 1st element

Chỉnh sửa theo câu hỏi trong bình luận. Đối với $@bạn có thể sử dụng nó như thế này:

set -- "${@:2}" #removed the 1st parameter

8
Lưu ý rằng nó không loại bỏ phần tử thứ 1 mà là phần tử của chỉ số 0 và gán lại các chỉ số. Nếu phần tử đầu tiên ở chỉ số 12, nó sẽ không xóa bất cứ thứ gì nhưng sẽ chỉ định lại các chỉ số để những gì đã từng ở chỉ số 12 bây giờ sẽ ở chỉ số 0. Có lẽ đó không phải là vấn đề đáng lo ngại trong trường hợp của OP nhưng có lẽ nên lưu ý tài liệu tham khảo trong tương lai. Hành vi là khác nhau với zshcác mảng không thưa thớt trái với ksh hoặc bash.
Stéphane Chazelas 18/03/13

3
Xin chào @StephaneChazelas. Số ít của "chỉ số" là " chỉ mục ". Cám ơn bạn đã góp ý!
Steven Lu

3
@manatwork - re: chỉnh sửa của bạn - tại sao không sử dụng shift?
don_crissti

1
@don_crissti, điểm tốt. Tôi tập trung vào sự khác biệt lập chỉ mục và không nghĩ xa hơn. Cũng đã ghi nhớ tình huống khi bạn cần loại bỏ số lượng vật phẩm khác nhau, ví dụ để giữ chính xác 3 cuối cùng: array=("${array[@]: -3}")set -- "${@: -3}". Vì vậy, bị mắc kẹt tại các chỉ số.
manatwork

1
shift $[$#-3]cho 3 người cuối cùng có lẽ nhanh hơn nhiều cho$@
Tino

0

Điều này đã làm tôi suy nghĩ. Vấn đề với sed / awk / tail là chúng theo từng dòng. Sau khi bạn xóa dòng đầu tiên, bạn phải ghi mọi dòng khác từ không gian mẫu vào tệp.

  • Bạn có thể sử dụng các lệnh sau để làm những gì bạn muốn trong vài giây.
  • Điều này sẽ ghi toàn bộ tập tin vào một mảng.
  • Xóa dòng đầu tiên khi nó đưa nó trở lại vào tập tin.

    readarray -t aLargeFile < <(cat largefile)
    echo "${aLargeFile[@]:1}" >largefile

Chỉ cần thay đổi largefiletên của tập tin của bạn.


Tại sao không sử dụng sed -i 1d largefilethay thế? Điều này thậm chí hoạt động cho các tệp lớn hơn RAM + trao đổi
Tino

0

Để loại bỏ một phần tử tại chỉ mục cụ thể, chúng ta có thể sử dụng unsetvà sau đó sao chép sang một mảng khác. Chỉ unsetlà không bắt buộc trong trường hợp này. Bởi vì unsetkhông loại bỏ phần tử, nó chỉ đặt chuỗi null thành chỉ mục cụ thể trong mảng.

declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in ${arr[@]}
do
    arr2[$i]=$element
    ((++i))
done
echo ${arr[@]}
echo "1st val is ${arr[1]}, 2nd val is ${arr[2]}"
echo ${arr2[@]}
echo "1st val is ${arr2[1]}, 2nd val is ${arr2[2]}"

Đầu ra là

aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd

-1
#!/bin/bash

q=( one two three four five )

echo -e "
  (remove) { [:range:] } <- [:list:]
                | [:range:] => return list with range removed range is in the form of [:digit:]-[:digit:]
"

function remove {
  if [[ $1 =~ ([[:digit:]])(-([[:digit:]]))?   ]]; then
    from=${BASH_REMATCH[1]}
    to=${BASH_REMATCH[3]}
  else
    echo bad range
  fi;shift
  array=( ${@} )
  local start=${array[@]::${from}}
  local rest
  [ -n "$to" ] && rest=${array[@]:((${to}+1))}  || rest=${array[@]:((${from}+1))}
  echo ${start[@]} ${rest[@]}
}

q=( `remove 1 ${q[*]}` )
echo ${q[@]}
~                                                                                                                                                              
~                       

4
Điều này sẽ tốt hơn nhiều nếu có một cái gì đó để giải thích cách nó hoạt động và không chỉ là một đốm mã. Và những gì với dấu ngã ở phía dưới?
một CVn

3
Nghiêm túc mà nói, bạn đúng. Điều này trông giống như nó được viết bởi một kẻ lưu manh, nhưng cảm ơn bạn. Tôi thực sự chỉ có thể lén điều này ở giữa những ngày phục vụ hamburger.
MageProspero

Nếu bất kỳ phần tử nào của q có khoảng trắng trong nó, phần tử này sẽ chia nó thành nhiều phần tử.
William Everett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.