Двумерный массив linux bash

Глава 25. Массивы

Новейшие версии Bash поддерживают одномерные массивы. Инициализация элементов массива может быть произведена в виде: variable[xx]. Можно явно объявить массив в сценарии, с помощью директивы declare: declare -a variable. Обращаться к отдельным элементам массива можно с помощью фигурных скобок, т.е.: $ .

Пример 25-1. Простой массив

Bash позволяет оперировать переменными, как массивами, даже если они не были явно объявлены таковыми.

Эти примеры еще раз подтверждают отсутствие контроля типов в Bash.

Пример 25-2. Форматирование стихотворения

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

При работе с массивами, некоторые встроенные команды Bash имеют несколько иной смысл. Например, unset — удаляет отдельные элементы массива, или даже массив целиком.

Пример 25-3. Некоторые специфичные особенности массивов

Как видно из предыдущего примера, обращение к $ или $ относится ко всем элементам массива. Чтобы получить количество элементов массива, можно обратиться к $ или к $ . $ — это длина (количество символов) первого элемента массива, т.е. $ .

Пример 25-4. Пустые массивы и пустые элементы

Разница между $ и $ такая же, как между $@ и $*. Эти свойства массивов широко применяются на практике.

Операция подстановки команд — array=( element1 element2 . elementN ), позволяет загружать содержимое текстовых файлов в массивы.

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

Массивы допускают перенос хорошо известных алгоритмов в сценарии на языке командной оболочки. Хорошо ли это — решать вам.

Пример 25-6. Старая, добрая: «Пузырьковая» сортировка

Можно ли вложить один массив в другой?

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

Пример 25-7. Вложенные массивы и косвенные ссылки

С помощью массивов, на языке командной оболочки, вполне возможно реализовать алгоритм Решета Эратосфена . Конечно же — это очень ресурсоемкая задача. В виде сценария она будет работать мучительно долго, так что лучше всего реализовать ее на каком либо другом, компилирующем, языке программирования, таком как C.

Пример 25-8. Пример реализации алгоритма Решето Эратосфена

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

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

Пример 25-9. Эмуляция структуры «СТЕК» («первый вошел — последний вышел»)

Иногда, манипуляции с «индексами» массивов могут потребовать введения переменных для хранения промежуточных результатов. В таких случаях вам предоставляется лишний повод подумать о реализации проекта на более мощном языке программирования, например Perl или C.

Пример 25-10. Исследование математических последовательностей

Bash поддерживает только одномерные массивы, но, путем небольших ухищрений, можно эмулировать многомерные массивы.

Пример 25-11. Эмуляция массива с двумя измерениями

По существу, двумерный массив эквивалентен одномерному, с тем лишь различием, что для индексации отдельных элементов используются два индекса — «строка» и «столбец» .

Более сложный пример эмуляции двумерного массива вы найдете в Пример A-11.

Источник

Массивы Bash Arrays

Bash Arrays

В этой статье мы рассмотрим массивы Bash и объясним, как их использовать в ваших скриптах Bash.

Массивы являются одной из наиболее используемых и фундаментальных структур данных. Вы можете думать, что массив — это переменная, которая может хранить несколько переменных внутри него.

Bash Arrays

Bash поддерживает одномерные числовые и ассоциативные типы массивов. Числовые массивы ссылаются с помощью целых чисел, а ассоциативные — с использованием строк.

Численно индексированные массивы могут быть доступны с конца, используя отрицательные индексы, индекс -1 ссылок на последний элемент. Индексы не должны быть смежными.

В отличие от большинства языков программирования, элементы массива Bash не обязательно должны быть одного типа данных. Вы можете создать массив, который содержит как строки, так и числа.

Bash не поддерживает многомерные массивы, и вы не можете иметь элементы массива, которые также являются массивами.

Не существует ограничения на максимальное количество элементов, которые могут быть сохранены в массиве.

Создание массивов Bash

Массивы в Bash могут быть инициализированы разными способами.

Создание численно проиндексированных массивов

Переменные Bash являются нетипизированными, любая переменная может быть использована в качестве индексированного массива без его объявления.

Чтобы явным образом объявить массив, используйте встроенное объявление:

Где index_* положительное целое число.

Другой способ создания числового массива — указать список элементов в скобках, разделенных пробелом:

Когда массив создается с использованием приведенной выше формы, индексация начинается с нуля, т.е. первый элемент имеет индекс 0 .

Создание ассоциативных массивов

В отличие от числового индексирования, ассоциативные массивы должны быть объявлены до того, как их можно будет использовать.

Чтобы объявить ассоциативный массив, используйте declare встроенную -A опцию (в верхнем регистре):

Ассоциативные массивы могут быть созданы с использованием следующей формы:

Вы также можете создать ассоциативный массив, используя форму ниже:

Операции с массивами

Поначалу синтаксис массивов Bash может показаться немного странным, но он станет более понятным после прочтения этой статьи.

Справочные элементы

Чтобы ссылаться на один элемент, вам нужно знать индекс элемента.

На любой элемент можно ссылаться, используя следующий синтаксис:

Напечатаем элемент с индексом 1 :

Если вы используете @ или * в качестве индекса, слово распространяется на всех членов массива. Чтобы напечатать все элементы, вы бы использовали:

Единственная разница между @ и * заключается в том, когда форма $ окружена двойными кавычками. В этом случае * расширяется до одного слова, где элементы массива разделяются пробелом. @ расширяет каждый элемент массива до отдельного слова. Это особенно важно при использовании формы для неграмотных элементов массива.

Чтобы напечатать ключи массива, добавьте ! оператор перед именем массива:

Длина массива

Чтобы получить длину массива, используйте следующую форму:

Цикл по массиву

Наиболее распространенный способ перебора каждого элемента в массиве — использование цикла for :

Код выше будет перебирать массив и печатать каждый элемент в новой строке:

Вот пример того, как распечатать все ключи и значения:

Другой способ перебрать массив — получить длину массива и использовать C style цикл:

Добавить новый элемент

Чтобы добавить новый элемент в массив bash и указать его индекс, используйте следующую форму:

Еще один способ добавления нового элемента в массив без указания индекса — использование += оператора. Вы можете добавить один или несколько элементов:

Удалить элемент

Чтобы удалить один элемент, вам нужно знать индекс элемента. Элемент можно удалить с помощью unset команды:

Давайте посмотрим на пример:

Вывод

Мы объяснили, как создавать числовые индексированные и ассоциативные массивы. Мы также показали, как перебирать массивы, вычислять длину массива, добавлять и удалять элементы.

Источник

Массивы bash

Предлагаю вашему вниманию перевод статьи Митча Фрейзера (Mitch Frazier) «Bash Arrays» с сайта linuxjournal.com.

Если вы используете «стандартную» оболочку *NIX-системы, возможно, вы не знакомы с такой полезной особенностью bash как массивы. Хотя массивы в bash не так круты, как в P-языках (Perl, Python и PHP) и других языках программирования, они часто бывают полезны.
Bash-массивы имеют только численные индексы, но они не обязательны к использованию, то есть вы не должны определять значения всех индексов в явном виде. Массив целиком может быть определен путем заключения записей в круглые скобки:

Отдельные записи могут быть определены с помощью знакомого всем синтаксиса (от Бейсика (да простит меня Дейкстра — прим. переводчика) до Фортрана):

Правда, обратное выглядит сравнительно более уродливо. Если нужно обратиться к определенной записи, тогда:

Из страницы man:

«Фигурные скобки нужны для предотвращения конфликтов при разворачивании полных путей к файлам.«

Кроме того, доступны следующие странноватые конструкции:

$ — сравнительно новое дополнение в bash и не является частью оригинальной реализации. Следующая конструкция демонстрирует пример простого использования массива. Обратите внимание на «[index]=value», это позволяет назначить конкретное значение конкретному номеру записи.

Запуск скрипта породит следующий вывод:

one
two
three
four
five

Array items and indexes:

0: one
1: two
2: three
3: four
5: five

Обратите внимание, что символ «@» может быть использован вместо «*» в конструкциях типа , результат будет одинаковым за исключением разворачивания записи в кавычках. «$*» и «$@» выведут записи в кавычках, «$» вернет каждую запись как одно слово, «$» вернет каждую запись в виде отдельных слов.

Следующий пример покажет, как кавычки и конструкции без кавычек возвращают строки (особенно важно, когда в этих строках есть пробелы):

Вывод при запуске:

Number of items in original array: 4

first item
second item
third
item

After unquoted expansion: 6

first
item
second
item
third
item

After * quoted expansion: 1

first item second item third item

After @ quoted expansion: 4

first item
second item
third
item

Источник

Многомерные массивы в Bash

Я планирую скрипт для управления некоторыми частями моих Linux-систем и сейчас решаю, хочу ли я использовать Баш или python.

Я бы предпочел сделать это как скрипт Bash просто потому, что команды проще, но реальный решающий фактор-конфигурация. Мне нужно иметь возможность хранить многомерный массив в файле конфигурации, чтобы сообщить скрипту, что делать с собой. Хранение простой ключ=значение в config файлы достаточно легко с bash, но единственный способ, который я могу придумать, чтобы сделать многомерный массив, — это двухслойный синтаксический анализатор, что-то вроде

но код Маршалла/unmarshall может стать медведем и его далеко не дружественным к пользователю для следующего бедного sap, который должен администрировать это. Если я не могу сделать это легко в bash, я просто напишу конфигурации в xml-файл и напишу скрипт на python.

есть ли простой способ сделать это в bash?

11 ответов

Bash не поддерживает многомерные массивы и хэши, и кажется, что вам нужен хэш, значения которого являются массивами. Это решение не очень красиво, решение с xml-файлом должно быть лучше:

Это то, что работал для меня.

независимо от используемой оболочки (sh, ksh, bash, . ) следующий подход работает довольно хорошо для n-мерных массивов (образец охватывает 2-мерный массив).

в образце разделителем строк (1-е измерение) является символ пробела. Для введения разделителя полей (2-го измерения) стандартный инструмент unix есть. Таким же образом можно использовать дополнительные сепараторы для дополнительных размеров.

конечно, производительность этого подхода не очень хорошо, но если производительность не является критерием, этот подход является довольно общим и может решить многие проблемы:

вывод этого образца выглядит следующим образом:

Bash не имеет многомерного массива. Но вы можете смоделировать несколько похожий эффект с ассоциативными массивами. Ниже приведен пример ассоциативного массива, претендующего на использование в качестве многомерного массива:

если вы не объявляете массив ассоциативным (с -A ), что выше не будет работать. Например, если вы опустите declare -A arr линия, echo печати 2 3 вместо 0 1 , потому что 0,0 , 1,0 и такие будут приняты как арифметика выражение и оценивается в 0 (значение справа от оператора запятой).

после многих проб и ошибок я на самом деле нахожу лучший, самый ясный и простой многомерный массив на bash-использовать обычный var. Да.

преимущества: вам не нужно перебирать большой массив, вы можете просто повторить «$var» и использовать grep/awk/sed. Это легко и ясно, и вы можете иметь столько столбцов, сколько вам нравится.

если вы хотите найти всех в Перу

только grep (sed) в третьем поле

если вы хотите только поле x

все в Перу, что называется Томас и просто вернуть свою фамилию

любой запрос, который вы можете придумать. суперлегких.

чтобы изменить элемент:

чтобы удалить строку, содержащую «x»

изменить другое поле в той же строке в зависимости от значения другого элемента

конечно, цикл тоже работает, если вы хочу сделать это

единственный gotcha iv’e нашел с этим, что вы должны всегда цитировать var (в примере; оба var и i) или вещи будут выглядеть так

и кто-то, несомненно, скажет, что это не сработает, если у вас есть пробелы в вашем входе, однако это может быть исправлено с помощью другого делиметра в вашем входе, например(используя символ utf8 теперь, чтобы подчеркнуть, что вы можете выбрать то, что ваш вход не будет содержать, но вы можете выбрать whatever ofc):

если вы хотите сохранить новые строки на входе, Вы можете преобразовать новую строку в что-то еще перед входом и преобразовать ее обратно на выходе(или не использовать bash. ). Наслаждайтесь!

расширение ответа Павла-вот моя версия работы с ассоциативными суб-массивами в bash:

он работает со смешанными значениями в основном массиве-strings / arrays / assoc. массивы

ключевым моментом здесь является, чтобы обернуть подмассивов в одинарные кавычки и использовать * вместо @ при хранении поддерева внутри основного массива, чтобы он хранился как одна строка, разделенная пробелом: «$«

тогда это позволяет легко анализировать массив из что при циклическом прохождении значений с IFS=’ ‘ read -a val

код выше выводит:

я публикую следующее, потому что это очень простой и понятный способ имитировать (по крайней мере, в некоторой степени) поведение двумерного массива в Bash. Он использует здесь-файл (см. руководство Bash) и read (команда bash builtin):

выход: Physicist Wolfgang Pauli was born in 1900 Physicist Werner Heisenberg was born in 1901 Physicist Albert Einstein was born in 1879 Physicist Niels Bohr was born in 1885

как это работает:

  • строки во временном созданном файле играют роль одномерных векторов, где пробелы (или что-то еще разделительный символ, который вы выбираете; см. Описание read команда в руководстве Bash) отделите элементы этих векторов.
  • затем, используя С -a опция, мы цикл над каждой строкой файла (пока мы не достигнем конца файла). Для каждой строки мы можем назначить нужные поля (= слова) массиву, который мы объявили непосредственно перед циклом. The до read команда предотвращает обратные косые черты от действия в качестве escape-символов, в случае мы набрали обратные косые черты в here-document physicists.$$ .

в заключение файл создается как 2D-массив, а его элементы извлекаются с помощью цикла над каждой строкой и с использованием возможности read команда для назначения слов элементам (индексированного) массива.

небольшое улучшение:

в приведенном выше коде, файл physicists.$$ вход в while цикл, так что он фактически передается . Однако, я обнаружил, что это вызывает проблемы, когда у меня есть другая команда задаете вопрос внутри while петли. Например, select команда ждет стандартного ввода, и если помещено внутри while цикл, он будет принимать входные данные от physicists.$$ , вместо запроса в командной строке для ввода данных пользователем. Чтобы исправить это, я использую на read , что позволяет читать из файлового дескриптора. Нам нужно только создать файловый дескриптор (с помощью ), соответствующие physicists.$$ и отдать его -u вариант чтения, как в следующем коде:

обратите внимание, что дескриптор файла закрывается в конце.

Я делаю это с помощью ассоциативные массивы С Баш 4 и параметр IFS к значению, которое можно определить вручную.

цель этого подхода состоит в том, чтобы иметь массивы в качестве значений ассоциативных ключей массива.

чтобы установить IFS обратно по умолчанию, просто снимите его.

вывод сценария ниже есть:

У меня есть довольно простое, но умное решение: Просто определите массив с переменными в его имени. Например:

Не знаю, помогает ли это, так как это не совсем то, что вы просили, но это работает для меня. (То же самое может быть достигнуто только с переменными без массива)

Bash не поддерживает многомерный массив,но мы можем реализовать с помощью ассоциированного массива. Здесь индексы являются ключом для извлечения значения. Ассоциированный массив доступен в bash версия 4.

Источник

Читайте также:  Iso образ windows это
Оцените статью