বাশে কীভাবে অ্যারে টুকরো করা যায়


194

ব্যাশ (1) ম্যান পৃষ্ঠাতে "অ্যারে" বিভাগটি দেখছি, আমি কোনও অ্যারে কাটানোর কোনও উপায় খুঁজে পাইনি।

সুতরাং আমি এই অত্যধিক জটিল ফাংশন নিয়ে এসেছি:

#!/bin/bash

# @brief: slice a bash array
# @arg1:  output-name
# @arg2:  input-name
# @args:  seq args
# ----------------------------------------------
function slice() {
   local output=$1
   local input=$2
   shift 2
   local indexes=$(seq $*)

   local -i i
   local tmp=$(for i in $indexes 
                 do echo "$(eval echo \"\${$input[$i]}\")" 
               done)

   local IFS=$'\n'
   eval $output="( \$tmp )"
}

এর মতো ব্যবহৃত:

$ A=( foo bar "a  b c" 42 )
$ slice B A 1 2
$ echo "${B[0]}"  # bar
$ echo "${B[1]}"  # a  b c

এই কাজ করতে একটি ভাল উপায় আছে কি?


আমি অনুসন্ধান করছিলাম কীভাবে অ্যারের শেষটি কাটা যায় এবং এখানেই নির্দেশিত হয়েছিল directed উত্তরটি এখানে পাওয়া যায়নি এবং এটি করা সদৃশ হবে কারণ আমি উত্তরটি এখানে stackoverflow.com/questions/44939747/… পেয়েছি । মূল ধারণাটি হ'ল আমাদের কাছে একটি গাণিতিক ভাব থাকতে পারে যেমন $ {# অ্যারে [@]} - (2 + 7) যেখানে দৈর্ঘ্যটি $ {অ্যারে: অফসেট: দৈর্ঘ্য in এ প্রত্যাশিত} এখানে সরবরাহিত উত্তরগুলির মধ্যে কোনওই এটি চিত্রিত করে না।
ডোমিনিক 108

উত্তর:


310

বাশ পৃষ্ঠায় প্যারামিটার সম্প্রসারণ বিভাগটি দেখুন manA[@]অ্যারের সামগ্রীগুলি ফেরত দেয় :1:2, সূচি 1 থেকে শুরু করে দৈর্ঘ্যের 2 টুকরা নেয়।

A=( foo bar "a  b c" 42 )
B=("${A[@]:1:2}")
C=("${A[@]:1}")       # slice to the end of the array
echo "${B[@]}"        # bar a  b c
echo "${B[1]}"        # a  b c
echo "${C[@]}"        # bar a  b c 42
echo "${C[@]: -2:2}"  # a  b c 42 # The space before the - is necesssary

নোট করুন যে "আব সি সি" একটি অ্যারের উপাদান (এবং এটিতে একটি অতিরিক্ত স্থান রয়েছে) সংরক্ষণ করা হয়েছে।


2
কুল। আমি অ্যারে বিভাগে দেখেছি, এবং এটি সেখানে দেখিনি।
চেন লেভি

36
এটি নির্বোধ চেন, এটি অ্যারে বিভাগে থাকবে কেন? * সার্ক
ডেল্টারে

1
@AquariusPower: সূচকের একটি অ্যারের তৈরি করুন এবং এটি যেভাবেই: idx=(${!A[@]}); echo ${idx[@]:1}
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

7
@ ফিউমারুর্মেল: বর্গাকার বন্ধনী সূচকগুলি ছাড়াই এটি করুন:${@:1:2}
পরবর্তী নির্দেশ না দেওয়া পর্যন্ত

5
@ ডেনিস উইলিয়ামসন আমি দেখতে পেয়েছি যে এটি করার $@আগে আমাকে একটি সঠিক অ্যারেতে রূপান্তর করা দরকার ছিল বা ফাঁকে ফাঁকে থাকা যুক্তিগুলি বিভক্ত হয়ে উঠবে:ARGS=( "$@" ); ARGS_AFTER_FIRST=( "${ARGS[@]:1}" )
বর্ডার ২

47

নির্দিষ্ট সূচী দিয়ে শুরু হওয়া অ্যারের সমস্ত উপাদান পেতে একটি সুবিধাজনক শর্টকাটও রয়েছে। উদাহরণস্বরূপ "$ {এ [@]: 1}" অ্যারের "লেজ" হবে, এটি অ্যারের প্রথম উপাদান ছাড়াই।

version=4.7.1
A=( ${version//\./ } )
echo "${A[@]}"    # 4 7 1
B=( "${A[@]:1}" )
echo "${B[@]}"    # 7 1

8
এবং আপনি যখন এতে ছিলেন:echo "${A[@]::1}" # 4
চেন লেভি

7
এটি দুর্দান্ত, তবে এটি লক্ষ্য করা উচিত যে যদি কোনও ফাংশনের মধ্যে ব্যবহার করা হয় তবে এটি পড়তে অবশ্যই কিছুটা পরিবর্তন করতে হবে "${${@}[@]:1}"
অ্যালেক্স গ্রে

@ অ্যালেক্সগ্রী: এটি আমাকে এখানে "খারাপ প্রতিস্থাপন" দেয়, তবে ঠিক ${@:2}কাজ করে।
নিক মাত্তিও

3

পাইথনের মতো অ্যারে স্লাইসিং ( রিবাশ লাইব্রেরি থেকে):

array_slice() {
    local __doc__='
    Returns a slice of an array (similar to Python).

    From the Python documentation:
    One way to remember how slices work is to think of the indices as pointing
    between elements, with the left edge of the first character numbered 0.
    Then the right edge of the last element of an array of length n has
    index n, for example:
    ```
    +---+---+---+---+---+---+
    | 0 | 1 | 2 | 3 | 4 | 5 |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
    -6  -5  -4  -3  -2  -1
    ```

    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice 1:-2 "${a[@]}")
    1 2 3
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice 0:1 "${a[@]}")
    0
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(array.slice 1:1 "${a[@]}")" ] && echo empty
    empty
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(array.slice 2:1 "${a[@]}")" ] && echo empty
    empty
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(array.slice -2:-3 "${a[@]}")" ] && echo empty
    empty
    >>> [ -z "$(array.slice -2:-2 "${a[@]}")" ] && echo empty
    empty

    Slice indices have useful defaults; an omitted first index defaults to
    zero, an omitted second index defaults to the size of the string being
    sliced.
    >>> local a=(0 1 2 3 4 5)
    >>> # from the beginning to position 2 (excluded)
    >>> echo $(array.slice 0:2 "${a[@]}")
    >>> echo $(array.slice :2 "${a[@]}")
    0 1
    0 1

    >>> local a=(0 1 2 3 4 5)
    >>> # from position 3 (included) to the end
    >>> echo $(array.slice 3:"${#a[@]}" "${a[@]}")
    >>> echo $(array.slice 3: "${a[@]}")
    3 4 5
    3 4 5

    >>> local a=(0 1 2 3 4 5)
    >>> # from the second-last (included) to the end
    >>> echo $(array.slice -2:"${#a[@]}" "${a[@]}")
    >>> echo $(array.slice -2: "${a[@]}")
    4 5
    4 5

    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice -4:-2 "${a[@]}")
    2 3

    If no range is given, it works like normal array indices.
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice -1 "${a[@]}")
    5
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice -2 "${a[@]}")
    4
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice 0 "${a[@]}")
    0
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array.slice 1 "${a[@]}")
    1
    >>> local a=(0 1 2 3 4 5)
    >>> array.slice 6 "${a[@]}"; echo $?
    1
    >>> local a=(0 1 2 3 4 5)
    >>> array.slice -7 "${a[@]}"; echo $?
    1
    '
    local start end array_length length
    if [[ $1 == *:* ]]; then
        IFS=":"; read -r start end <<<"$1"
        shift
        array_length="$#"
        # defaults
        [ -z "$end" ] && end=$array_length
        [ -z "$start" ] && start=0
        (( start < 0 )) && let "start=(( array_length + start ))"
        (( end < 0 )) && let "end=(( array_length + end ))"
    else
        start="$1"
        shift
        array_length="$#"
        (( start < 0 )) && let "start=(( array_length + start ))"
        let "end=(( start + 1 ))"
    fi
    let "length=(( end - start ))"
    (( start < 0 )) && return 1
    # check bounds
    (( length < 0 )) && return 1
    (( start < 0 )) && return 1
    (( start >= array_length )) && return 1
    # parameters start with $1, so add 1 to $start
    let "start=(( start + 1 ))"
    echo "${@: $start:$length}"
}
alias array.slice="array_slice"

1

বলুন আমি ব্যবহারকারীর কাছ থেকে একটি অ্যারে পড়ছি, তারপরে আমি উপাদানটি 3 থেকে 7 পর্যন্ত উভয়কেই দেখতে চাই।

cnt=0
while read var;
    do
    myarr[cnt]=$var
    cnt=$((cnt+1)) 
    done


echo ${myarr[@]:3:5}

4
আপনার কোডের স্লাইস সিনট্যাক্সটি 8 বছরের পুরানো স্বীকৃত উত্তরের মতো। আপনার উত্তর নতুন কিছু যোগ করে না।
মেলপোমেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.