Bash, чтение строки за строкой, разбиение строк на строку, разделенное на ",", сохранение в массив - PullRequest
0 голосов
/ 11 июня 2019

Мне нужно читать файл построчно, а каждую строку делить на "," и сохранять в массив.

Файл source_file.

usl-coop,/root
usl-dev,/bin

Скрипт.

i=1
while read -r line; do
IFS="," read -ra para_$i <<< $line
echo ${para_$i[@]}
((i++))
done < source_file

Ожидаемый вывод.

para_1[0]=usl-coop
para_1[1]=/root
para_2[0]=usl-dev
para_2[1]=/bin

Скрипт выдаст ошибку об эхо.

./sofimon.sh: line 21: ${para_$i[@]}: bad substitution

Когда я эхо-массив массив по одному полю, например

echo para_1[0]

это показывает, что переменные хранятся.

Но мне нужно использовать его с переменной внутри, что-то вроде этого.

${para_$i[1]}

Возможно ли это сделать?

Спасибо.

S.

Ответы [ 2 ]

3 голосов
/ 11 июня 2019

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

declare -A para
i=1
while IFS=, read -r -a line; do
    for j in ${!line[@]}; do
       para[$i,$j]="${line[$j]}"
    done
   ((i++)) ||:
done < source_file
declare -p para

будет выводить:

declare -A para=([1,0]="usl-coop" [1,1]="/root" [2,1]="/bin" [2,0]="usl-dev" )

Без изменения вашего скрипта вы можете использовать расширение косвенной переменной .Иногда он используется в более простых сценариях:

i=1
while IFS="," read -r -a para_$i; do
        n="para_$i[@]"
        echo "${!n}"
        ((i++)) ||:
done < source_file
declare -p ${!para_*}

или в основном то же самое с nameref именованной ссылкой на другую переменную (примечание: посмотрите, как [@]должен быть частью переменной при косвенном раскрытии, но не в именованной ссылке):

i=1
while IFS="," read -r -a para_$i; do
        declare -n n
        n="para_$i"
        echo "${n[@]}"
        ((i++)) ||:
done < source_file
declare -p ${!para_*}

оба приведенных выше сценария будут выводить одинаково:

usl-coop /root
usl-dev /bin
declare -a para_1=([0]="usl-coop" [1]="/root")
declare -a para_2=([0]="usl-dev" [1]="/bin")

Тем не менее, я думаю, что выне должен читать ваш файл в память вообще.Это просто плохой дизайн.Оболочка и оболочка построены на передаче ваших файлов с конвейерами, потоками, fifo, перенаправлениями, подстановками процессов и т. Д. Без сохранения / копирования / сохранения файла.Если у вас есть файл для анализа, вы должны передать его другому процессу, проанализировать и сохранить результат, не сохраняя весь ввод в памяти.Если вы хотите, чтобы некоторые данные находились внутри файла, используйте grep или awk.

0 голосов
/ 11 июня 2019

Вот короткий awk скрипт, который выполняет задачу.

awk 'BEGIN{FS=",";of="para_%d[%d]=%s\n"}{printf(of, NR, 0, $1);printf(of, NR, 1, $2)}' input.txt

Укажите желаемый результат.

1006 * * Пояснение:
BEGIN{
  FS=",";                # set field seperator to `,`
  of="para_%d[%d]=%s\n"  # define common printf output format
}
{                         # for each input line
  printf(of, NR, 0, $1);  # output for current line, [0], left field
  printf(of, NR, 1, $2)   # output for current line, [1], right field
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...