создание списка / массива из текстового файла или файла csv с использованием bash - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь написать небольшой скрипт оболочки для анализа простого файла CSV (всего один столбец) и присвоить значение в каждом значении переменной, которая должна быть массивом / списком.

Пример file:

Title_ID
123
456
789
000

Нужен скрипт для синтаксического анализа файла и вывода результатов в переменную с названием title, так что echo ${title[1]} возвращает 456

Вот мой текущий script

while read line; do
temp_title[$i]="$line"
i=$((i++))
done < ./title_master_list.csv

Я получаю следующую ошибку zsh: temp_title: присвоение недействительного нижнего индекса звонило

Есть идеи, что я делаю неправильно?

1 Ответ

0 голосов
/ 22 апреля 2020

С man zshparam:

Элементы нумеруются начиная с 1, если не установлена ​​опция KSH_ARRAYS, в этом случае они нумеруются с нуля.

Итак, проблема в том, что вы пытаетесь использовать индексирование, начинающееся с 0, а не 1. Используйте:

#!/usr/bin/zsh
typeset -a temp_title
i=1
while IFS= read -r line; do
    temp_title[i++]="$line" # Note the postincrement in the index expression
done < ./title_master_list.csv
echo "${temp_title[1]}"

Но есть и лучшие способы сделать это, без использования al oop, с использованием zsh флагов расширения параметров :

temp_title=("${(@f)"$(<./title_master_list.csv)"}")

Это разбивает файл на новых строках в массив.

Это также может быть сделано с одним read:

IFS=$'\n' read -r -d '' -A temp_title < ./title_master_list.csv

Для полноты, другие подходы, основанные на l oop:

Настройка опции для использования массивов на основе 0:

#!/usr/bin/zsh
setopt KSH_ARRAYS
typeset -a temp_title
i=0
while IFS= read -r line; do
    temp_title[i++]="$line"
done < ./title_master_list.csv
echo "${temp_title[0]}"

Не используйте индексы, используйте +=() для добавления в массив:

#!/usr/bin/zsh
typeset -a temp_title
while IFS= read -r line; do
    temp_title+=("$line")
done < ./title_master_list.csv
echo "${temp_title[1]}"

При использовании bash вместо zsh используйте встроенный mapfile чтобы прочитать файл в массив:

mapfile -t temp_title < ./title_master_list.csv

Действительно старые версии, возможно, придется использовать:

IFS=$'\n' read -r -d '' -a temp_title < ./title_master_list.csv

(аналогично версии zsh, но использует строчные буквы -a )

...