Здравствуйте, я пытаюсь разобрать файл в массив, содержащий пустые элементы.
Образец файла (test
)
test11|test12|test13|test14
test21||test23|test24
следующая функция просто печатает элементы массива
test_func()
{
local param=($@)
echo "1: ${param[1]}, 2: ${param[2]}, 3: ${param[3]}, 4: ${param[4]}"
}
И теперь я вызываю эту функцию следующим образом
while IFS=\| read f1 f2 f3 f4
do
arr=("$f1" "$f2" "$f3" "$f4")
test_func ${arr[@]}
done < test
Я использую zsh 5.8.1 (x86_64-ubuntu-linux-gnu)
. Я получил следующий вывод
1: test11, 2: test12, 3: test13, 4: test14
1: test21, 2: test23, 3: test24, 4:
Обратите внимание, что во второй строке элементы смещены влево.
Я не уверен, что я делаю неправильно здесь. Может кто-нибудь, пожалуйста, помогите мне в этом?
Спасибо
Попробуйте: test_func() {local param=("$@"); echo "1: ${param[0]}, 2: ${param[1]}, 3: ${param[2]}, 4: ${param[3]}"; }
(двойная кавычка $@
и первый индекс равен 0).
Я использовал двойные кавычки, как предложил @Philippe. Что касается второго комментария, я получаю результат 1: , 2: test11, 3: test12, 4: test13
@SudiptaRoy, для 2-й строки вам нужно вывести 2-е пустое поле ||
как 2: ,
. Вы можете применить gawk?
@RomanPerekhrest, не могли бы вы уточнить. Это именно то, чего я хочу.
@SudiptaRoy, вы можете применить / использовать gawk?
Также двойная кавычка ${arr[@]}
. Если вы не заключаете двойные кавычки $@
или ${arr[@]}
, пустые позиционные параметры или ячейки массива пропускаются. В то время как с двойными кавычками они раскрываются как отдельные пустые слова.
@Philippe: не должно иметь значения.
@RenaudPacalet: Я тоже это подозревал, но попытка с arr=(a b c '')
и test_func "$arr[@]"
тоже не сработала. Чтобы убедиться, что я не путаю пустой элемент с неопределенным элементом, я запускаю код с set -u
, и даже с двойными кавычками я получаю параметр test_func:3: param[4]: not set, который демонстрирует, что параметр действительно отсутствует.
@RenaudPacalet: После некоторых экспериментов (печать $4
в начале функции) я обнаружил, что действительно присваивание ($@)
удаляет элемент, поэтому вы правы в том, что и ${arr[@]}
, и $@
должны быть заключены в кавычки. Я видел, что у вас уже было это в ответе, но вы удалили его. Ваша единственная ошибка в вашем ответе была частью индексации, потому что массивы zsh индексируются, начиная с 1. Могу ли я предложить вам повторно ввести правильную часть вашего ответа?
Расширения параметров без кавычек не подлежат разбиению на слова, но ${arr[@]}
не создает отдельные слова из-за разбиения на слова. Если вы оставите расширение без кавычек, оно создаст слова без кавычек, а не расширения параметров без кавычек, и пустая строка без кавычек просто «уйдет».
@RenaudPacalet Если вы восстановите свой ответ (и исправите индексы), я удалю свой.
@chepner Мой ответ был bash
-единственным, который я написал до того, как ОП пояснил, что они хотят использовать zsh
. Поскольку я не эксперт по zsh
, я предпочитаю, чтобы вы ответили.
Хорошо, просто проверяю :) Ничего в вашем ответе не было специфичным для bash
и применимо и к zsh
. (Нужно было обновить только индексы массива, но даже пункт об 0-индексации верен, если установлена опция KSH_ARRAYS
. zsh
не что иное, как гибкость...)
@RenaudPacalet, ваше предложение действительно было правильным. Если вы опубликуете ответ, я приму его.
Вам нужно поставить в кавычки и ${arr[@]}
, и $@
, чтобы сохранить пустое жало, производимое каждым из них.
Расширения параметров без кавычек не подлежат разбиению на слова, но отдельные элементы, создаваемые расширением массива, не являются следствием разбиения на слова. Они являются отдельными словами сами по себе, поэтому отсутствие кавычек упомянутых выше расширений приводит к появлению слов без кавычек. Пустая строка без кавычек просто "уходит". Если оставить $arr[@]
без кавычек, пустая строка никогда не попадет в test_func
, а если оставить $@
без кавычек, пустая строка не будет присутствовать в присваивании param
.
test_func()
{
local param=("$@")
echo "1: ${param[1]}, 2: ${param[2]}, 3: ${param[3]}, 4: ${param[4]}"
}
while IFS=\| read f1 f2 f3 f4
do
arr=("$f1" "$f2" "$f3" "$f4")
test_func "${arr[@]}"
done < test
Это намного проще с командой awk
:
awk -F'\\|' -v OFS=', ' '{ for(i=1;i<=NF;i++) $i=i": "$i }1' test.txt
1: test11, 2: test12, 3: test13, 4: test14
1: test21, 2: , 3: test23, 4: test24
Можете ли вы добавить двойные кавычки, такие как
"$@"
и"${arr[@]}"
?