Как извлечь определенный элемент из массива в BASH?
Я создаю свой массив в bash следующим образом:
while read line
do
myarr[$index]=$line
index=$(($index+1))
done < lines.txt
Файл "lines.txt" состоит из следующих строк:
hello big world!
how are you
where am I
После создания массива ${myarr[@]}
я могу легко получить доступ к каждому элементу (строке) в этом массиве, выполнив следующую команду:
echo ${myarr[2]}
Но что, если я хочу извлечь только слово world!
? Возможно ли извлечь world!
из первого элемента массива myarr
? Более того, возможно ли извлечь любое последнее слово из элемента массива myarr
?
Я знаю, что в Python можно сделать myarr[0][-1]
и это сработает, как насчет bash?
3 ответ(ов)
Это один из многих способов:
set ${myarr[2]}
echo $3
В этом примере мы используем команду set
, чтобы установить позиционные параметры в Bash. Когда вы вызываете set ${myarr[2]}
, вы берёте элементы из массива myarr
, начиная с третьего элемента (индекса 2) и устанавливаете их как позиционные параметры. После этого, вызов echo $3
выводит третий позиционный параметр, который теперь соответствует элементу массива myarr[2]
.
Убедитесь, что массив myarr
был инициализирован заранее, чтобы избежать ошибок.
Вы можете извлекать слова из строки (каждый элемент массива - это и есть строка) с помощью модификаторов в расширении переменных: #
(удалить префикс), ##
(удалить префикс, жадный), %
(удалить суффикс) и %%
(удалить суффикс, жадный).
Вот пример, как это работает:
$ myarr=('hello big world!' 'how are you' 'where am I')
$ echo "${myarr[0]}" # Полный первый элемент массива
hello big world!
$ echo "${myarr[0]##* }" # Чтобы получить последнее слово, удаляем префикс до последнего пробела
world!
$ echo "${myarr[0]%% *}" # Чтобы получить первое слово, удаляем суффикс, начиная с первого пробела
hello
$ tmp="${myarr[0]#* }" # Второе слово сложнее; сначала удаляем до первого пробела...
$ echo "${tmp%% *}" # ...затем получаем первое слово из оставшегося
big
$ tmp="${myarr[0]#* * }" # Третье слово (которое может быть и не последним)? Удаляем до второго пробела...
$ echo "${tmp%% *}" # ...а затем снова получаем первое слово
world!
Как вы можете видеть, это может стать довольно изощренным, но в какой-то момент предложение @chepner превратить строку в массив становится гораздо проще. Также формулы, которые я предлагаю для извлечения второго и последующих слов, немного хрупкие: если вы используете мою формулу для извлечения третьего слова из строки, в которой только два слова, первое обрезание не сработает, и в результате будет напечатано первое (!) слово вместо пустого. Кроме того, если в строке есть два пробела подряд, это будет восприниматься как слово нулевой длины с пробелами по обе стороны...
Кстати, при создании массива я считаю немного более чистым использовать +=(newelement)
, чем явно отслеживать индекс массива:
myarr=()
while read line; do
myarr+=("$line")
done < lines.txt
Чтобы вывести конкретный элемент из массива по индексу, можно использовать следующую команду:
echo ${my_array[2]}
Если вы хотите вывести все элементы массива, используйте следующий цикл:
for i in "${my_array[@]}"
do
echo $i
done
Таким образом, для доступа к отдельным элементам массива используется индекс, а для перебора всех элементов — цикл for
.
Как пройтись по массиву строк в Bash?
Добавить новый элемент в массив в Bash без указания индекса
Как разделить строку на массив в Bash?
Как объединить элементы массива Bash в строку с разделителем?
Как сохранить порядок ассоциативного массива?