LINUX.ORG.RU
решено ФорумAdmin

Странное поведение mapfile в BASH

 


0

1

Здравствуйте!

Преамбула:

cat ./ddd
первая строка
вторая строка

четвёртая строка

шестая строка
Амбула:
mapfile b < <(cat ./ddd)
echo ${#b[@]}
6
А вот тут засада:
i=0; for n in ${b[@]}; do echo $((i+1)) ${b[i]}; ((++i)); done
1 первая строка
2 вторая строка
3
4 четвёртая строка
5
6 шестая строка
7
8
Откуда две лишние строки? (С реальным файлом из 17 строк получил 79 строк, с 18 по 79 — пустые).

ЧЯДНТ?



Последнее исправление: Cave-Canem (всего исправлений: 1)
for ((i=0;i<${#b[@]};i++)); do echo $((i+1)) ${b[i]}; done



сделай echo ${b[@]} и увидишь почему такой цикл был

kiotoze ★★★★
()
Ответ на: комментарий от kiotoze

Сделал, но не увидел

echo ${b[@]}
первая строка вторая строка четвёртая строка шестая строка

Разве что в выводе 8 значений, но ведь:

echo ${#b[@]}
6
Ведь число элементов массива 6? И (например)
echo ${b[0]}
первая строка
т.е. первый элемент массива состоит из двух слов, разделенных пробелом

Конструкция с C-подобным синтаксисом работает:

for ((i=0;i<${#b[@]};i++)); do echo $((i+1)) ${b[i]}; done
1 первая строка
2 вторая строка
3
4 четвёртая строка
5
6 шестая строка
Не мог бы на пальцах объяснить почему не правильно работает мой вариант?

Cave-Canem
() автор топика
Ответ на: Сделал, но не увидел от Cave-Canem

Все, разобрался, не хватало кавычек:

i=0; for n in "${b[@]}"; do echo $((i+1)) ${b[i]}; ((i++)); done
1 первая строка
2 вторая строка
3
4 четвёртая строка
5
6 шестая строка

Всем Спасибо!

Cave-Canem
() автор топика
Ответ на: комментарий от legolegs

Ты ведь знаешь про утилиту nl и про cat -n, верно?

Это пока вам не понадобиться пронумеровать как-нибудь так: а) б) в)...

vodz ★★★★★
()
Ответ на: комментарий от vodz

И для этого есть менее болезненный путь:

# ls / | awk '{ getline nl < "./alphabet"; print nl,$0}'
а bin
б boot
в dev
г etc
д home
е lib
ж lib64
з lost+found
и media
к mnt
л opt
м proc
н root
о run
п sbin
р srv
с sys
т tmp
у usr
ф var

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Вариант без файла с буквами (для bash):

ls | awk 'BEGIN { ARGC=2;} { getline nl < ARGV[2]; print nl,$0}' - <(echo -ne {,а,б,в,г,д,е,ж,з,и,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ы,э,ю,я}{а,б,в,г,д,е,ж,з,и,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ы,э,ю,я}$'\n' | tr -d ' ')

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

И для этого есть менее болезненный путь

Ну офигеть. Вы read из bash заменили на awk. А потом ещё и tr добавили... В bash получить букву по номеру элементарно: ${alphas:NL:1}

vodz ★★★★★
()
Ответ на: комментарий от vodz

Я заменил сложную и хрупкую конструкцию на простую и дубовую.

legolegs ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.