#bash #unix
#bash #unix
Вопрос:
У меня есть индексированный массив с именем wlist[], который содержит кучу слов, и я хочу разобрать их на несколько массивов, чтобы каждый новый массив состоял из слов одинаковой длины. Я продолжаю получать синтаксические ошибки из wcholder$i =("${wlist[$counter]}")
я также попытался изменить wcholder$i =("${wlist[$counter]}")
с var=wlist[$counter] eval wcholder$i =("${!var}")
Код:
#!/bin/bash
.
.
.
# mlength=length of the longest word in wlist[]
# wlength=contains length of every word in the same order in wlist[]
for ((i=1; i<=mlength; i))
do
declare -a wcholder$i
done
counter=1
for i in "${wlength[@]}"; do
eval wcholder$i =("${wlist[$counter]}")
((counter =1))
done
Комментарии:
1. Это можно сделать, но на практике «нумерованные имена переменных» довольно раздражают в работе и обычно указывают на то, что вы пытаетесь сделать что-то, для чего shell является неправильным инструментом. Есть ли какая-то особая причина, по которой вам нужно это сделать?
2. bash не дает вам много возможностей для создания структур данных. Вы получаете «скаляры», одномерные массивы с числовым индексом и одномерные ассоциативные массивы. Существуют также позиционные параметры, которые действуют более или менее как массив.
3. К вашему сведению, это классический пример проблемы XY
4. предполагая, что вы ищете анаграммы из отдельных слов, какую выгоду вы видите от первой сортировки слов по длине? как вы планировали использовать свои массивы в обработке анаграмм? (re: ссылка на «проблему XY» Гленна — интересно, может ли быть полезно отступить назад и посмотреть на общую картину, то есть на обработку анаграмм)
5. голосую за это, даже если это проблема XY. Достойная попытка работы с анаграммами. Но shell не является подходящим инструментом для этого. Оболочки хороши для выполнения заданий и работы с файлами (даже с логикой), но логику данных следует оставить awk, perl, python (возможно, c, в зависимости от ваших целей). Я рекомендую изучить
awk
анаграммы (там должны быть какие-то). Также хороший учебник по Awk , но там есть новые концепции, которые нужно понять. Удачи.
Ответ №1:
Вы можете эмулировать многомерный массив bash
тем же способом, что и в awk
: используя ассоциированный массив с ключами, построенными из индексов разных уровней — в случае следующего примера, length,index
. Первое слово длиной 3 хранится в ассоциированном массиве с ключом 3,0
, второе 3,1
и так далее. Максимальный индекс каждой длины хранится в отдельном массиве.
#!/usr/bin/env bash
declare -a wordlist=(cat rate bat late rat mate other words) positions
declare -A wordsbylen
for word in "${wordlist[@]}"; do
len=${#word}
pos=${positions[$len]:-0}
wordsbylen[$len,$pos]=$word
positions[$len]=$((pos 1))
done
for len in "${!positions[@]}"; do
printf "Words of length %d: " "$len"
for ((pos=0; pos < ${positions[$len]}; pos )); do
printf "%s " "${wordsbylen[$len,$pos]}"
done
printf "n"
done
Запуск этого вывода:
Words of length 3: cat bat rat
Words of length 4: rate late mate
Words of length 5: other words
Я согласен с комментаторами, которые предлагают использовать другой язык с лучшей поддержкой сложных структур данных, хотя — код в конечном итоге будет намного проще и понятнее.
Комментарии:
1. Вы также можете просто создать массив, в котором каждый элемент представляет собой строку слов, разделенных пробелами, длиной этого индекса, и при необходимости превратить их в массивы, но приведенный выше вариант более надежен в том смысле, что он будет работать, скажем, с фразами, а не только с отдельными словами.