Разбор массива с пустым элементом

Здравствуйте, я пытаюсь разобрать файл в массив, содержащий пустые элементы.

Образец файла (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: 

Обратите внимание, что во второй строке элементы смещены влево.

Я не уверен, что я делаю неправильно здесь. Может кто-нибудь, пожалуйста, помогите мне в этом?

Спасибо

Можете ли вы добавить двойные кавычки, такие как "$@" и "${arr[@]}"?

Philippe 30.01.2023 10:02

Попробуйте: test_func() {local param=("$@"); echo "1: ${param[0]}, 2: ${param[1]}, 3: ${param[2]}, 4: ${param[3]}"; } (двойная кавычка $@ и первый индекс равен 0).

Renaud Pacalet 30.01.2023 10:10

Я использовал двойные кавычки, как предложил @Philippe. Что касается второго комментария, я получаю результат 1: , 2: test11, 3: test12, 4: test13

Sudipta Roy 30.01.2023 10:14

@SudiptaRoy, для 2-й строки вам нужно вывести 2-е пустое поле || как 2: ,. Вы можете применить gawk?

RomanPerekhrest 30.01.2023 10:20

@RomanPerekhrest, не могли бы вы уточнить. Это именно то, чего я хочу.

Sudipta Roy 30.01.2023 10:28

@SudiptaRoy, вы можете применить / использовать gawk?

RomanPerekhrest 30.01.2023 10:28

Также двойная кавычка ${arr[@]}. Если вы не заключаете двойные кавычки $@ или ${arr[@]}, пустые позиционные параметры или ячейки массива пропускаются. В то время как с двойными кавычками они раскрываются как отдельные пустые слова.

Renaud Pacalet 30.01.2023 10:37

@Philippe: не должно иметь значения.

user1934428 30.01.2023 14:10

@RenaudPacalet: Я тоже это подозревал, но попытка с arr=(a b c '') и test_func "$arr[@]" тоже не сработала. Чтобы убедиться, что я не путаю пустой элемент с неопределенным элементом, я запускаю код с set -u, и даже с двойными кавычками я получаю параметр test_func:3: param[4]: not set, который демонстрирует, что параметр действительно отсутствует.

user1934428 30.01.2023 14:13

@RenaudPacalet: После некоторых экспериментов (печать $4 в начале функции) я обнаружил, что действительно присваивание ($@) удаляет элемент, поэтому вы правы в том, что и ${arr[@]}, и $@ должны быть заключены в кавычки. Я видел, что у вас уже было это в ответе, но вы удалили его. Ваша единственная ошибка в вашем ответе была частью индексации, потому что массивы zsh индексируются, начиная с 1. Могу ли я предложить вам повторно ввести правильную часть вашего ответа?

user1934428 30.01.2023 14:23

Расширения параметров без кавычек не подлежат разбиению на слова, но ${arr[@]} не создает отдельные слова из-за разбиения на слова. Если вы оставите расширение без кавычек, оно создаст слова без кавычек, а не расширения параметров без кавычек, и пустая строка без кавычек просто «уйдет».

chepner 30.01.2023 14:42

@RenaudPacalet Если вы восстановите свой ответ (и исправите индексы), я удалю свой.

chepner 30.01.2023 14:48

@chepner Мой ответ был bash-единственным, который я написал до того, как ОП пояснил, что они хотят использовать zsh. Поскольку я не эксперт по zsh, я предпочитаю, чтобы вы ответили.

Renaud Pacalet 30.01.2023 15:16

Хорошо, просто проверяю :) Ничего в вашем ответе не было специфичным для bash и применимо и к zsh. (Нужно было обновить только индексы массива, но даже пункт об 0-индексации верен, если установлена ​​опция KSH_ARRAYS. zsh не что иное, как гибкость...)

chepner 30.01.2023 15:19

@RenaudPacalet, ваше предложение действительно было правильным. Если вы опубликуете ответ, я приму его.

Sudipta Roy 31.01.2023 06:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
15
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно поставить в кавычки и ${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

Другие вопросы по теме