2013-11-07 4 views
2

Я искал сайт очень тщательно, но не смог подобрать подходящий ответ - скорее всего, я не задавал правильных вопросов.bash: разделите текстовый файл на фигурные скобки на массив

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

[1] 
-75.4532 75.8273 
-115.00 64.5 
-90.00 74.3333 
-100.00 72.4167 
-110.00 69.00 
-120.8 56.284 
[2] 
-70.00 73.75 
-100.00 69.3333 
-110.00 65.1533 
-90.00 71.5833 
-80.00 73.00 
[3] 
-100.00 67.5 
-67.7133 72.6611 
-80.00 71.5 
-90.00 70.00 
-110.00 63.8667 
-115.8 60.836 

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

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

Всего наилучшего!

+0

Вы ищете двухмерный массив? Баш не поддерживает это. В качестве альтернативы мы могли бы создать одну строку для каждого индекса с строками, разделенными '\ n'. Вы действительно хотите хранить несколько тысяч строк в памяти одновременно? – cdarke

+0

Я думал о том, где его хранить, и в среднем мы говорим о 200 строках. Максимум составляет около 4000 строк и является редким явлением. – Chris

ответ

2

Вы можете использовать СЭД массировать файл в определение Баш массива:

declare -a "$(sed 's/\[/" &/g; s/\]/&="/g' file | sed '1s/^"/arr=(/; $s/$/")/')" 
echo "${arr[2]}" 
echo 
echo ${arr[2]} 
-70.00 73.75 
-100.00 69.3333 
-110.00 65.1533 
-90.00 71.5833 
-80.00 73.00 

-70.00 73.75 -100.00 69.3333 -110.00 65.1533 -90.00 71.5833 -80.00 73.00 

Печать с и без кавычек, чтобы продемонстрировать разницу

+0

Отличная идея, хотя я думаю, что один gawk был бы проще использовать 'RS = '\\ [[0-9] + \\]'' – anubhava

+0

glenn hackman, спасибо за этот пример sed. Я вижу, где я совершил свою ошибку. – Chris

2

использовать комбинацию read -d (для установить разделитель записей) и IFS (для установки полевого сепаратора):

# read content from file 
content="$(<input_filename)" 

# append record separator to avoid dropping the last record 
content="$content[" 

# read into array 
arr=() 
while IFS=']' read -d '[' sub value; do 
    arr[$sub]=$value 
done <<<"$content" 

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

unset arr[0] 

Теперь вы можете цикл по элементам:

for value in "${arr[@]}"; do 
    program < "$value" 
done 

или, если вам нужно индексирует 1 на основе, а также:

for ((i=1; i<=${#arr[@]}; i++)); do 
    program "$i" "$value" 
done 

Надеюсь, что это поможет!

+0

Очень хорошо объясненный ответ. Спасибо! – Chris

Смежные вопросы