Я прочитал некоторые записи по этому вопросу, например, в здесь или здесь, но мне не удалось заставить мой код работать. Это должно быть очень просто.
Мне нужно добавить элементы из цикла while после небольшого преобразования в пустой список. Мой код выглядит следующим образом:
folder='/path/to/directories/'
ls $folder | while read dir ; do
if [[ $dir =~ ANF-* ]]; then
names=()
ls $folder/$dir/FASTQS | while read file ; do
name=$(echo $file | cut -d "_" -f 1-3 )
echo $name
names+=("$name")
done
echo ${names[*]} #Also tried echo ${names[@]}
fi
done
Первое «эхо» работает, поэтому оно проходит через условное выражение и во второй цикл.
Я также попытался использовать «объявить -a» для создания пустого массива.
Если я попытаюсь добавить $file в список, это тоже не сработает.
Я думаю, что проблема заключается в добавлении действия, потому что, если я создаю непустой массив, я получаю элементы массива во втором «эхе».
Заранее большое спасибо. RX
В качестве примечания, вместо использования ls (вывод которого заведомо хрупкий), вы должны использовать globs: for dir in "$folder"/*; do, который решает проблему установки переменной в подпроцессе. а также устойчив к именам файлов.
Кроме того, ANF-* как регулярное выражение означает ANF, ANF-, ANF--, ANF--- и т. д., что, вероятно, не то, что вы имели в виду. Если вы имели в виду «начинается с ANF-», вы должны были использовать ^ANF-.* (.* для «любого числа любого символа») или просто ^ANF-, потому что =~ проверяет подсовпадения; или [[ $dir == ANF-* ]] (шаблоны оболочки вместо регулярного выражения).
И, наконец, я не думаю, что вам нужен вложенный цикл; вы можете сделать что-то вроде for file in "$folder"/ANF-*/FASTQS/*; do, и в зависимости от того, как выглядят имена файлов, вы, вероятно, могли бы использовать расширение параметра для получения нужных частей.
Я попробую, но я не думаю, что это проблема, я попал в цикл, и я получаю файлы, которые меня интересуют, модифицированные, проблема заключается в добавлении имен в список.
Вы меняете names в подпроцессе (внутренний | while read создает его), затем вы получаете доступ к names вне этого подпроцесса (echo ${names[*]}), но все изменения внутри подпроцесса исчезают. Самое простое исправление — изменить ls [...] | while read file; do [...]; done на while read file; do [...]; done < <(ls [...]), но обратите внимание, что при этом по-прежнему используется множество антишаблонов, таких как использование вывода ls программно.



Попробуйте заключить эхо в двойные кавычки:
folder='/path/to/directories/'
ls $folder | while read dir ; do
if [[ $dir =~ ANF-* ]]; then
names=()
local iteration=1
ls $folder/$dir/FASTQS | while read file ; do
name=$(echo $file | cut -d "_" -f 1-3 )
echo $name
names+=("$name")
echo "iteration $iteration"
iteration=$((iteration+1))
declare -p names
done
echo "${names[@]}"
# you can show the array like this:
declare -p names
fi
done
Ваш массив names изменяется, но когда цикл завершается, изменения исчезают. Посмотрите на ответы @Benjamin W. любезно указал.
Большое спасибо, но я добавил ваши модификации, но они все еще не работают. Элементы цикла не добавляются в список. Цикл работает. Я получаю список файлов интересующих меня каталогов и могу изменять имена внутри цикла.
Цитирование не имеет к этому никакого отношения; проблема заключается в изменении переменной в подоболочке.
@Rachael, ваш вопрос был отредактирован модератором (@Benjamin W.), и он указывает на предыдущий ответ ... вы его проверили?
Не модератор, а просто такой же пользователь :) И вопрос не редактировался, а помечался как дубликат.
Проблема изменяется без каких-либо проблем, проблема заключается в добавлении элемента, а не в его изменении.
См. также БашFAQ/024.