Новости

масиви

Новітні версії Bash підтримують одномірні масиви. Ініціалізація елементів масиву може бути проведена у вигляді: variable [xx]. Можна явно оголосити масив в сценарії, за допомогою директиви declare: declare -a variable. Звертатися до окремих елементів масиву можна за допомогою фігурних дужок, тобто .: $ {variable [xx]}.

Приклад 25-1. простий масив

#! / Bin / bash area [11] = 23 area [13] = 37 area [51] = UFOs # Масиви не вимагають, щоб послідовність елементів в масиві була безперервною. # Деякі елементи масиву можуть залишатися неініціалізованих. # "Дірки" в масиві не є помилкою. echo -n "area [11] =" echo $ {area [11]} # необхідні {фігурні дужки} echo -n "area [13] =" echo $ {area [13]} echo "вміст area [51] = $ {area [51]}. " # Звернення до неініціалізованих елементам дає порожній рядок. echo -n "area [43] =" echo $ {area [43]} echo "(елемент area [43] - неініціалізованих)" echo # Сума двох елементів масиву, записана в третій елемент area [5] = `expr $ {area [11]} + $ {area [13]} `echo" area [5] = area [11] + area [13] "echo -n" area [5] = "echo $ {area [5]} area [6] = `expr $ {area [11]} + $ {area [51]}` echo "area [6] = area [11] + area [51]" echo -n "area [6] =" echo $ {area [6]} # Ця спроба закінчиться невдачею, оскільки складання цілого числа з рядком не допускається. echo; echo; echo # ------------------------------------------------ ----------------- # Інший масив, "area2". # І інший спосіб ініціалізації масиву ... # array_name = (XXX YYY ZZZ ...) area2 = (нуль один два три чотири) echo -n "area2 [0] =" echo $ {area2 [0]} # Ага, індексація починається з нуля (перший елемент масиву має індекс [0], а не [1]). echo -n "area2 [1] =" echo $ {area2 [1]} # [1] - другий елемент масиву. # ------------------------------------------------- ---------------- echo; echo; echo # ----------------------------------------------- # ще один масив, "area3". # І ще один спосіб ініціалізації ... # array_name = ([xx] = XXX [yy] = YYY ...) area3 = ([17] = сімнадцять [21] = двадцать_одін) echo -n "area3 [17] = "echo $ {area3 [17]} echo -n" area3 [21] = "echo $ {area3 [21]} # ---------------------- ------------------------- exit 0

Bash дозволяє оперувати змінними, як масивами, навіть якщо вони не були явно оголошені такими.

string = abcABC123ABCabc echo $ {string [@]} # abcABC123ABCabc echo $ {string [*]} # abcABC123ABCabc echo $ {string [0]} # abcABC123ABCabc echo $ {string [1]} # Нічого не виводиться! # Чому? echo $ {# string [@]} # 1 # Кількість елементів в масиві. # Спасибі Michael Zick за цей приклад. Ці приклади ще раз підтверджують відсутність контролю типів в Bash .

Приклад 25-2. форматування вірші

#! / Bin / bash # poem.sh # Рядки з вірша (одна строфа). Line [1] = "Мій дядько самих чесних правил," Line [2] = "Коли не в жарт занедужав;" Line [3] = "Він поважати себе примусив," Line [4] = "І краще вигадати не міг." Line [5] = "Його приклад іншим наука ..." # Атрибути. Attrib [1] = "О. С. Пушкін" Attrib [2] = "\" Євгеній Онєгін \ "" for index in 1 2 3 4 5 # П'ять рядків. do printf "% s \ n" "$ {Line [index]}" done for index in 1 -2 # Два рядки додаткових атрибутів. do printf "% s \ n" "$ {Attrib [index]}" done exit 0

При роботі з окремими елементами масиву можна використовувати специфічний синтаксис, навіть стандартні команди і оператори Bash адаптовані для роботи з масивами.

array = (нуль один два три чотири п'ять) echo $ {array [0]} # нуль echo $ {array: 0} # нуль # Підстановка параметра - першого елемента. echo $ {array: 1} # оль # Підстановка параметра - першого елемента, # + починаючи з позиції # 1 (з 2-го символу). echo $ {# array} # 4 # Довжина першого елемента масиву. array2 = ([0] = "перший елемент" [1] = "другий елемент" [3] = "четвертий елемент") echo $ {array2 [0]} # перший елемент echo $ {array2 [1]} # другий елемент echo $ {array2 [2]} # # Елемент неініціалізованих, тому на екран нічого не виводиться. echo $ {array2 [3]} # четвертий елемент

При роботі з масивами, деякі вбудовані команди Bash мають дещо інший сенс. наприклад, unset - видаляє окремі елементи масиву, або навіть масив цілком.

Приклад 25-3. Деякі специфічні особливості масивів

#! / Bin / bash declare -a colors # Допускається оголошення масиву без вказівки його розміру. echo "Введіть ваші улюблені кольори (розділяючи їх пробілами)." read -a colors # Введіть хоча б 3 кольори для демонстрації деяких властивостей масивів. # Специфічний ключ команди 'read', # + дозволяє вводити кілька елементів масиву. echo element_count = $ {# colors [@]} # Отримання кількості елементів в масиві. # Element_count = $ {# colors [*]} - дає той же результат. # # Змінна "@" дозволяє "розбивати" рядок в лапках на окремі слова # + (виділяються слова, розділені пробілами). index = 0 while [ "$ index" -lt "$ element_count"] do # Список всіх елементів в масиві. echo $ {colors [$ index]} let "index = $ index + 1" done # Кожен елемент масиву виводиться в окремому рядку. # Якщо цього не потрібно, то використовуйте echo -n "$ {colors [$ index]}" # # Еквівалентний цикл "for": # for i in "$ {colors [@]}" # do # echo "$ i" # done # (Спасибі SC) echo # Ще один, більш елегантний, спосіб виведення списку всіх елементів масиву. echo $ {colors [@]} # $ {colors [*]} дає той же результат. echo # Команда "unset" видаляє елементи з масиву, або навіть масив цілком. unset colors [1] # Видалення 2-го елемента масиву. # Той же ефект дає команда colors [1] = echo $ {colors [@]} # Список всіх елементів масиву - 2-й елемент відсутній. unset colors # Видалення всього масиву. # Той же ефект мають команди unset colors [*] # + і unset colors [@]. echo; echo -n "Масив квітів спустошений." echo $ {colors [@]} # Список елементів масиву порожній. exit 0

Як видно з попереднього прикладу, звернення до $ {array_name [@]} або $ {array_name [*]} відноситься до всіх елементів масиву. Щоб отримати кількість елементів масиву, можна звернутися до $ {# array_name [@]} або до $ {# array_name [*]}. $ {# array_name} - це довжина (кількість символів) першого елемента масиву, тобто $ {array_name [0]}.

Приклад 25-4. Порожні масиви і порожні елементи

#! / Bin / bash # empty-array.sh # Висловлюю свою подяку Stephane Chazelas за цей приклад, # + і Michael Zick за його доопрацювання. # Порожній масив - це не те ж саме, що масив з порожніми елементами. array0 = (перший другий третій) array1 = ( '') # "array1" має один порожній елемент. array2 = () # Масив "array2" не має жодного елемента, тобто порожній. echo ListArray () {echo echo "Елементи масиву array0: $ {array0 [@]}" echo "Елементи масиву array1: $ {array1 [@]}" echo "Елементи масиву array2: $ {array2 [@]}" echo echo "Довжина першого елемента масиву array0 = $ {# array0}" echo "Довжина першого елемента масиву array1 = $ {# array1}" echo "Довжина першого елемента масиву array2 = $ {# array2}" echo echo "Число елементів в масиві array0 = $ {# array0 [*]} "# 3 echo" Число елементів в масиві array1 = $ {# array1 [*]} "# 1 (сюрприз!) echo" Число елементів в масиві array2 = $ {# array2 [*]} "# 0} # ============================================= ====================== ListArray # Спробуємо додати нові елементи в масиви # Додавання нових елементів в масиви. array0 = ( "$ {array0 [@]}" "новий1") array1 = ( "$ {array1 [@]}" "новий1") array2 = ( "$ {array2 [@]}" "новий1") ListArray # або array0 [$ {# array0 [*]}] = "новий2" array1 [$ {# array1 [*]}] = "новий2" array2 [$ {# array2 [*]}] = "новий2" ListArray # Тепер уявімо кожен масив як 'стек' ( 'stack') # Команди вище, можна вважати командами 'push' - додавання нового значення на вершину стека # 'Глибина' стека: height = $ {# array2 [@]} echo echo "Глибина стека array2 = $ height "# Команда 'pop' - виштовхування елемента стека, що знаходиться на вершині: unset array2 [$ {# array2 [@]} - 1] # Індексація масивів починається з нуля height = $ {# array2 [@]} echo echo "POP" echo "Глибина стека array2, після виштовхування = $ height" ListArray # Вивести т Тільки 2-й і 3-й елементи масиву array0 from = 1 # Індексація масивів починається з нуля to = 2 # declare -a array3 = ($ {array0 [@]: 1: 2}) echo echo "Елементи масиву array3: $ {array3 [@]} "# Заміна елементів за шаблоном declare -a array4 = ($ {array0 [@] / другий / 2-й}) echo echo" Елементи масиву array4: $ {array4 [@]} "# Заміна рядків за шаблоном declare -a array5 = ($ {array0 [@] // новий? / старий}) echo echo "Елементи масиву array5: $ {array5 [@]}" # Треба лише звикнути до такого запису ... declare -a array6 = ($ {array0 [@] # * новий}) echo # Це може вас кілька здивувати echo "Елементи масиву array6: $ {array6 [@]}" declare -a array7 = ($ {array0 [@] # новий1} ) echo # Тепер це вас вже не повинно дивувати echo "Елементи масив а array7: $ {array7 [@]} "# виглядає дуже схоже на попередній варіант ... declare -a array8 = ($ {array0 [@] / новий1 /}) echo echo" Елементи масиву array8: $ {array8 [@ ]} "# Отже, що ви можете сказати про все це? # Строкові операції виконуються послідовно, над кожним елементом # + в масиві var [@]. # Таким чином, BASH підтримує векторні операції # Якщо в результаті операції виходить порожній рядок, то # + елемент масиву "зникає". # Питання: це відноситься до рядків в "строгих" або "м'яких" лапках? zap = 'новий *' declare -a array9 = ($ {array0 [@] / $ zap /}) echo echo "Елементи масиву array9: $ {array9 [@]}" # "... А з платформи кажуть:" це місто Ленінград! "..." declare -a array10 = ($ {array0 [@] # $ zap}) echo echo "Елементи масиву array10: $ {array10 [@]}" # Порівняйте масиви array7 і array10 # Порівняйте масиви array8 і array9 # Відповідь: в "м'яких" лапках. exit 0

Різниця між $ {array_name [@]} і $ {array_name [*]} така ж, як між $ @ І $ * . Ці властивості масивів широко застосовуються на практиці.

# Копіювання масивів. array2 = ( "$ {array1 [@]}") # або array2 = "$ {array1 [@]}" # Додати елемент. array = ( "$ {array [@]}" "новий елемент") # або array [$ {# array [*]}] = "новий елемент" # Спасибі SC

операція підстановки команд - array = (element1 element2 ... elementN), дозволяє завантажувати вміст текстових файлів в масиви.

#! / Bin / bash filename = sample_file # cat sample_file # # 1 abc # 2 de fg declare -a array1 array1 = ( `cat" $ filename "| tr '\ n' ''`) # Завантаження вмісту файлу # $ filename в масив array1. # Висновок на stdout. # З заміною символів переведення рядка на прогалини. echo $ {array1 [@]} # список елементів масиву. # 1 abc 2 de fg # # Кожне "слово", в текстовому файлі, виділення від інших пробілами # + заноситься в окремий елемент масиву. element_count = $ {# array1 [*]} echo $ element_count # 8

Приклад 25-5. Копіювання і конкатенація масивів

#! / Bin / bash # CopyArray.sh # # Автор: Michael Zick. # Використовується з його дозволу. # "Прийняти з масиву з заданим ім'ям записати в масив з заданим ім'ям" # + або "власний Оператор Привласнення". CpArray_Mac () {# Оператор Привласнення echo -n 'eval' echo -n "$ 2" # Ім'я масиву-результату echo -n '= ($ {' echo -n "$ 1" # Ім'я вихідного масиву echo -n '[@] }) '# Все це могло б бути об'єднано в одну команду. # Це лише питання стилю. } Declare -f CopyArray # "Покажчик" на функцію CopyArray = CpArray_Mac # Оператор Привласнення Hype () {# Вихідний масив з ім'ям в $ 1. # (Злити з масивом, що містить "- Справжній Рок-н-Ролл".) # Повернути результат в масиві з ім'ям $ 2. local -a TMP local -a hype = (- Справжній Рок-н-Ролл) $ ($ CopyArray $ 1 TMP) TMP = ($ {TMP [@]} $ {hype [@]}) $ ($ CopyArray TMP $ 2 )} declare -a before = (Advanced Bash Scripting) declare -a after echo "Масив before = $ {before [@]}" Hype before after echo "Масив after = $ {after [@]}" # Ще? echo "Що таке $ {after [@]: 4: 2}?" declare -a modest = ($ {after [@]: 2: 1} $ {after [@]: 3: 3}) # ---- виділення підрядка ---- echo "Масив Modest = $ {modest [@ ]} "# А що в масиві 'before'? echo "Масив Before = $ {before [@]}" exit 0

-

Масиви допускають перенесення добре відомих алгоритмів в сценарії на мові командної оболонки. Чи добре це - вирішувати вам.

Приклад 25-6. Стара, добра: "Бульбашкова" сортування

#! / Bin / bash # bubble.sh: "Бульбашкова" сортування. # На кожному проході по сортованого масиву, # + порівнюються два суміжних елемента, і, якщо необхідно, вони міняються місцями. # В кінці першого проходу, самий "важкий" елемент "опускається" в кінець масиву. # В кінці другого проходу, наступний за "тяжкості" елемент займає друге місце знизу. # І так далі. # Кожен наступний прохід вимагає на одне порівняння менше попереднього. # Тому ви повинні помітити прискорення роботи сценарію на останніх проходах. exchange () {# Поміняти місцями два елементи масиву. local temp = $ {Countries [$ 1]} # Тимчасова змінна Countries [$ 1] = $ {Countries [$ 2]} Countries [$ 2] = $ temp return} declare -a Countries # Оголошення масиву, # + необов'язково, оскільки він явно инициализируется нижче. # Чи припустимо виконувати ініціалізацію масиву в нескольки рядках? # ТАК! Countries = (Нідерланди Україна Заїр Туреччина Росія Ємен Сирія \ Бразилія Аргентина Нікарагуа Японія Мексика Венесуела Греція Англія \ Ізраїль Перу Канада Оман Данія Уельс Франція Кенія \ Занаду Катар Ліхтенштейн Угорщина) # "Занаду" - це міфічна держава, де, згідно з Coleridge, # + Kubla Khan побудував величний палац. clear # Очищення екрану. echo "0: $ {Countries [*]}" # Список елементів несортоване масиву. number_of_elements = $ {# Countries [@]} let "comparisons = $ number_of_elements - 1" count = 1 # Номер проходу. while [ "$ comparisons" -gt 0] # Початок зовнішнього циклу do index = 0 # Скинути індекс перед початком кожного проходу. while [ "$ index" -lt "$ comparisons"] # Початок внутрішнього циклу do if [$ {Countries [$ index]} \> $ {Countries [ `expr $ index + 1 ']}] # Якщо елементи стоять не по порядку ... # Оператор \> виконує порівняння ASCII-рядків # + всередині одиночних квадратних дужок. # If [[$ {Countries [$ index]}> $ {Countries [ `expr $ index + 1 ']}]] # + дає той же результат. then exchange $ index `expr $ index + 1 '# Поміняти місцями. fi let "index + = 1" done # Кінець внутрішнього циклу let "comparisons - = 1" # Оскільки самий "важкий" елемент вже "опустився" на дно, # + то на кожному наступному проході потрібно виконувати на одне порівняння менше. echo echo "$ count: $ {Countries [@]}" # Вивести вміст масиву після кожного проходу. echo let "count + = 1" # Збільшити лічильник проходів. done # Кінець зовнішнього циклу exit 0

-

Чи можна вкласти один масив в інший?

#! / Bin / bash # Вкладений масив. # Автор: Michael Zick. AnArray = ($ (ls --inode --ignore-backups --almost-all \ --directory --full-time --color = none --time = status \ --sort = time -l $ {PWD} )) # Команди опції. # Прогалини важливі. . . SubArray = ($ {AnArray [@]: 11: 1} $ {AnArray [@]: 6: 5}) # Масив має два елементи, кожен з яких, в свою чергу, є масивом. echo "Поточний каталог і дата останнього зміни:" echo "$ {SubArray [@]}" exit 0

-

Вкладені масиви, в комбінації з непрямими посиланнями , Надають в розпорядження програміста ряд чудових можливостей

Приклад 25-7. Вкладені масиви і непрямі посилання

#! / Bin / bash # embedded-arrays.sh # Вкладені масиви і непрямі посилання. # Автор: Dennis Leeuw. # Використовується з його дозволу. # Доповнено автором документа. ARRAY1 = (VAR1_1 = value11 VAR1_2 = value12 VAR1_3 = value13) ARRAY2 = (VARIABLE = "test" STRING = "VAR1 = value1 VAR2 = value2 VAR3 = value3" ARRAY21 = $ {ARRAY1 [*]}) # Вкладення масиву ARRAY1 в масив ARRAY2. function print () {OLD_IFS = "$ IFS" IFS = $ '\ n' # Висновок кожного елемента масиву # + в окремому рядку. TEST1 = "ARRAY2 [*]" local $ {! TEST1} # Подивіться, що станеться, якщо прибрати цей рядок. # Непряма посилання. # Дозволяє отримати доступ до компонентів $ TEST1 # + в цій функції. # Подивимося, що вийшло. echo echo "\ $ TEST1 = $ TEST1" # Просто ім'я змінної. echo; echo echo "{\ $ TEST1} = $ {! TEST1}" # Висновок на екран вмісту змінної. # Це те, що дає # + непряме посилання. echo echo "-------------------------------------------"; echo echo # Висновок змінної echo "Змінна VARIABLE: $ VARIABLE" # Висновок елементів рядка IFS = "$ OLD_IFS" TEST2 = "STRING [*]" local $ {! TEST2} # Непряма посилання (той же, що і вище). echo "Елемент VAR2: $ VAR2 з рядка STRING" # Висновок елемента масиву TEST2 = "ARRAY21 [*]" local $ {! TEST2} # Непряма посилання. echo "Елемент VAR1_1: $ VAR1_1 з масиву ARRAY21"} print echo exit 0

-

За допомогою масивів, на мові командної оболонки, цілком можливо реалізувати алгоритм Решето Ератосфена. Звичайно ж - це дуже ресурсномістка завдання. У вигляді сценарію вона буде працювати болісно довго, так що краще всього реалізувати її на будь-якому іншому, компілює, мовою програмування, такому як C.

Приклад 25-8. Приклад реалізації алгоритму Решето Ератосфена

#! / Bin / bash # sieve.sh # Решето Ератосфена # Дуже старий алгоритм пошуку простих чисел. # Цей сценарій запускається у багато разів повільніше # ніж аналогічна програма на C. LOWER_LIMIT = 1 # Починаючи з 1. UPPER_LIMIT = 1000 # До 1000. # (Ви можете встановити верхню межу і вище ... якщо вам є чим себе зайняти.) PRIME = 1 NON_PRIME = 0 declare -a Primes # Primes [] - масив. initialize () {# Ініціалізація масиву. i = $ LOWER_LIMIT until [ "$ i" -gt "$ UPPER_LIMIT"] do Primes [i] = $ PRIME let "i + = 1" done # Все числа в заданому діапазоні вважати простими, # поки не доведено протилежне. } Print_primes () {# Висновок індексів елементів масиву Primes [], які визнані простими. i = $ LOWER_LIMIT until [ "$ i" -gt "$ UPPER_LIMIT"] do if [ "$ {Primes [i]}" -eq "$ PRIME"] then printf "% 8d" $ i # 8 пробілів перед числом надають чіткий табличний висновок на екран. fi let "i + = 1" done} sift () # Відсіювання складених чисел. {Let i = $ LOWER_LIMIT + 1 # Нам відомо, що 1 - це просте число, тому почнемо з 2. until [ "$ i" -gt "$ UPPER_LIMIT"] do if [ "$ {Primes [i]}" -eq "$ PRIME"] # Не слід перевіряти вдруге числа, які вже визнані складовими. then t = $ i while [ "$ t" -le "$ UPPER_LIMIT"] do let "t + = $ i" Primes [t] = $ NON_PRIME # Все числа, які діляться на $ t без залишку, позначити як складові. done fi let "i + = 1" done} # Виклик функцій. initialize sift print_primes # Це називається структурним програмуванням. echo exit 0 # ---------------------------------------------- - # # Код, наведений нижче, не виконується через команди exit, що стоїть вище. # Покращена версія, запропонована Stephane Chazelas, # працює трохи швидше. # Повинен бути викликані з аргументом командного рядка, який визначає верхня межа. UPPER_LIMIT = $ 1 # З командного рядка. let SPLIT = UPPER_LIMIT / 2 # Розглядати подільники тільки до середини діапазону. Primes = ( '' $ (seq $ UPPER_LIMIT)) i = 1 until (((i + = 1)> SPLIT)) # Числа з верхньої половини діапазону можуть не розглядатися. do if [[-n $ Primes [i]]] then t = $ i until (((t + = i)> UPPER_LIMIT)) do Primes [t] = done fi done echo $ {Primes [*]} exit 0

Порівняйте цей сценарій з генератором простих чисел, що не використовують масивів, Приклад A-18 .

-

Масиви дозволяють емулювати деякі структури даних, підтримка яких в Bash не передбачена.

Приклад 25-9. Емуляція структури "СТЕК" ( "перший увійшов - останній вийшов")

#! / Bin / bash # stack.sh: Емуляція структури "СТЕК" ( "перший увійшов - останній вийшов") # Подібно стеку процесора, цей "стек" зберігає і повертає дані за принципом # + "перший увійшов - останній вийшов ". BP = 100 # Базовий покажчик на масив-стек. # Дно стека - 100-й елемент. SP = $ BP # Покажчик вершини стека. # Спочатку - стек порожній. Data = # Вміст вершини стека. # Слід використовувати додаткову змінну, # + через обмеження на діапазон повертаються функціями значень. declare -a stack push () # Помістити елемент на вершину стека. {If [-z "$ 1"] # А взагалі, є що поміщати на стек? then return fi let "SP - = 1" # Перемістити покажчик стека. stack [$ SP] = $ 1 return} pop () # Зняти елемент з вершини стека. {Data = # Очистити змінну. if [ "$ SP" -eq "$ BP"] # Стек порожній? then return fi # Це оберігає від виходу SP за кордон стека - 100, Data = $ {stack [$ SP]} let "SP + = 1" # Перемістити покажчик стека. return} status_report () # Висновок допоміжної інформації. {Echo "-------------------------------------" echo "ЗВІТ" echo "Покажчик стека SP = $ SP "echo" З стека був знятий елемент \ "" $ Data "\" "echo" ---------------------------- --------- "echo} # ===================================== ================== # А тепер побавимося. echo # Спробуємо виштовхнути щось з пустого стека. pop status_report echo push garbage pop status_report # заштовхнути garbage, виштовхнути garbage. value1 = 23; push $ value1 value2 = skidoo; push $ value2 value3 = FINAL; push $ value3 pop # FINAL status_report pop # skidoo status_report pop # 23 status_report # Перший увійшов - останній вийшов! # Зверніть увагу як змінюється покажчик стека на кожному виклику функцій push і pop. echo # ================================================ ======= # Вправи: # ----------- # 1) Змініть функцію "push ()" таким чином, # + щоб вона дозволяла розміщувати на стек кілька значень за один виклик. # 2) Змініть функцію "pop ()" таким чином, # + щоб вона дозволяла знімати зі стека кілька значень за один виклик. # 3) Спробуйте написати найпростіший калькулятор, який виконує 4 арифметичних дії? # + Використовуючи цей приклад. exit 0

-

Іноді, маніпуляції з масивів можуть зажадати введення змінних для зберігання проміжних результатів. У таких випадках вам надається зайвий привід подумати про реалізацію проекту на більш потужному мовою програмування, наприклад Perl або C.

Приклад 25-10. Дослідження математичних послідовностей

#! / Bin / bash # Горезвісна "Q-послідовність" Дугласа Хольфштадтера * Douglas Hofstadter): # Q (1) = Q (2) = 1 # Q (n) = Q (n - Q (n-1)) + Q (n - Q (n-2)), для n> 2 # Це "хаотична" послідовність цілих чисел з непередбачуваною поведінкою. # Перші 20 членів послідовності: # 1 1 2 3 3 4 5 5 6 6 6 8 8 8 10 9 10 11 11 12 # Див. Книгу Дугласа Хольфштадтера, "Goedel, Escher, Bach: An Eternal Golden Braid", # p. 137, ff. LIMIT = 100 # Знайти перші 100 членів послідовності LINEWIDTH = 20 # Число членів послідовності, що виводяться на екран в одному рядку Q [1] = 1 # Перші два члена послідовності рівні 1. Q [2] = 1 echo echo "Q-послідовність [ перші $ LIMIT членів]: "echo -n" $ {Q [1]} "# Вивести перші два члена послідовності. echo -n "$ {Q [2]}" for ((n = 3; n <= $ LIMIT; n ++)) # C-подібне оформлення циклу. do # Q [n] = Q [n - Q [n-1]] + Q [n - Q [n-2]] для n> 2 # Цей вислів необхідно розбити на окремі дії, # оскільки Bash не дуже добре підтримує складні арифметичні дії над елементами масивів. let "n1 = $ n1" # n1 let "n2 = $ n2" # n2 t0 = `expr $ n - $ {Q [n1]} '# n - Q [n1] t1 = `expr $ n - $ {Q [n2]} '# n - Q [n2] t0 = $ {Q [t0]} # Q [n - Q [n-1]] T1 = $ {Q [t1]} # Q [n - Q [n-2]] Q [n] = `expr $ T0 + $ T1` # Q [n - Q [n-1]] + Q [n - Q [n- 2]] echo -n "$ {Q [n]}" if [ `expr $ n% $ LINEWIDTH` -eq 0] # Якщо виведено чергові 20 членів в рядку. then # то echo # перейти на новий рядок. fi done echo exit 0 # Цей сценарій реалізує ітеративний алгоритм пошуку членів Q-послідовності. # Рекурсивних реалізацію, як більш інтуїтивно зрозумілу, залишаю вам, як вправи. # Увага: рекурсивний пошук членів послідовності буде займати * дуже * тривалий час.

-

Bash підтримує тільки одномірні масиви, але, шляхом невеликих хитрощів, можна емулювати багатовимірні масиви.

Приклад 25-11. Емуляція масиву з двома вимірами

#! / Bin / bash # Емуляція двовимірного масиву. # Другий вимір представлено як послідовність рядків. Rows = 5 Columns = 5 declare -a alpha # char alpha [Rows] [Columns]; # Необов'язкове оголошення масиву. load_alpha () {local rc = 0 local index for i in ABCDEFGHIJKLMNOPQRSTU VWXY do local row = `expr $ rc / $ Columns` local column =` expr $ rc% $ Rows` let "index = $ row * $ Rows + $ column "alpha [$ index] = $ i # alpha [$ row] [$ column] let" rc + = 1 "done # Простіший варіант # declare -a alpha = (ABCDEFGHIJKLMNOPQRSTU VWXY) # але при такому оголошенні другий вимір масиву завуальовано . } Print_alpha () {local row = 0 local index echo while [ "$ row" -lt "$ Rows"] # Висновок вмісту масиву через підрядник do local column = 0 while [ "$ column" -lt "$ Columns"] do let "index = $ row * $ Rows + $ column" echo -n "$ {alpha [index]}" # alpha [$ row] [$ column] let "column + = 1" done let "row + = 1" echo done # Простіший еквівалент: # echo $ {alpha [*]} | xargs -n $ Columns echo} filter () # фільтрування негативних індексів. {Echo -n "" if [[ "$ 1" -ge 0 && "$ 1" -lt "$ Rows" && "$ 2" -ge 0 && "$ 2" -lt "$ Columns"]] then let "index = $ 1 * $ Rows + $ 2 "echo -n" $ {alpha [index]} "# alpha [$ row] [$ column] fi} rotate () # Поворот масиву на 45 градусів {local row local column for ((row = Rows ; row> -Rows; row--)) # В зворотному порядку. do for ((column = 0; column <Columns; column ++)) do if [ "$ row" -ge 0] then let "t1 = $ column - $ row" let "t2 = $ column" else let "t1 = $ column "let" t2 = $ column + $ row "fi filter $ t1 $ t2 # Відфільтрувати негативний індекс. done echo; echo done # Поворот масиву виконаний на основі прикладів (стор. 143-146) # з книги "Advanced C Programming on the IBM PC", автор Herbert Mayer # (див. бібліографію). } # ------------------------------------------------ ----- # load_alpha # Ініціалізація масиву. print_alpha # Висновок на екран. rotate # Повернути на 45 градусів проти годинникової стрілки. # ------------------------------------------------- ---- # # Вправи: # ----------- # 1) Зробіть ініціалізацію і висновок масиву на екран # + ​​простішим і елегантним способом. # # 2) Поясніть принцип роботи функції rotate (). exit 0

По суті, двовимірний масив еквівалентний одномерному, з тією лише різницею, що для індексації окремих елементів використовуються два індекси - і.

Більш складний приклад емуляції двовимірного масиву ви знайдете в Приклад A-11 .

Чому?
Array0 [@] // новий?
Declare -a array8 = ($ {array0 [@] / новий1 /}) echo echo" Елементи масиву array8: $ {array8 [@ ]} "# Отже, що ви можете сказати про все це?
Питання: це відноситься до рядків в "строгих" або "м'яких" лапках?
Echo "Що таке $ {after [@]: 4: 2}?
Quot; declare -a modest = ($ {after [@]: 2: 1} $ {after [@]: 3: 3}) # ---- виділення підрядка ---- echo "Масив Modest = $ {modest [@ ]} "# А що в масиві 'before'?
Чи припустимо виконувати ініціалізацію масиву в нескольки рядках?
If [-z "$ 1"] # А взагалі, є що поміщати на стек?
If [ "$ SP" -eq "$ BP"] # Стек порожній?

Уважаемые партнеры, если Вас заинтересовала наша продукция, мы готовы с Вами сотрудничать. Вам необходимо заполнить эту форму и отправить нам. Наши менеджеры в оперативном режиме обработают Вашу заявку, свяжутся с Вами и ответят на все интересующее Вас вопросы.

Или позвоните нам по телефонам: (048) 823-25-64

Организация (обязательно) *

Адрес доставки

Объем

Как с вами связаться:

Имя

Телефон (обязательно) *

Мобильный телефон

Ваш E-Mail

Дополнительная информация: