Вопрос или проблема
Дан файл file.txt
:
первая строка
вторая строка
третья строка
Это работает в bash
:
while IFS=' ' read -a args; do
echo "${args[0]}"
done < file.txt
Чтобы получить
первая
вторая
третья
То есть, мы смогли читать файл построчно, и на каждой строке мы дополнительно разбивали строку на массив, используя пробел в качестве разделителя. Но в zsh
результатом является ошибка: read: bad option: -a
.
Как мы можем добиться в zsh
такого же результата, как в bash
? Я пробовал несколько решений, но так и не смог разбить строку на массив, используя пробелы в качестве разделителя.
Из man zshbuiltins
видно, что в zsh
используется -A
вместо -a
.
read [ -rszpqAclneE ] [ -t [ num ] ] [ -k [ num ] ] [ -d delim ]
[ -u n ] [ name[?prompt] ] [ name ... ]
...
-A Первое имя принимается как имя массива
и все слова присваиваются ему.
Следовательно, команда будет следующей
while IFS=' ' read -A args; do
echo "${args[1]}"
done < file.txt
Обратите внимание, что по умолчанию нумерация массивов в zsh
начинается с 1
, в то время как в bash
— с 0
.
$ man zshparam
...
Индексы массивов
...
Элементы нумеруются, начиная с 1, если только не установлена опция
KSH_ARRAYS, в этом случае они нумеруются с нуля.
Поздно, но вот что я использую для разделения по нижним подчеркиваниям в zsh
. Может сработать и в других оболочках.
# Разделить по нижним подчеркиваниям
var=
parts=(${(@s:_:)var})
echo $parts
for val in $parts; do
echo $val
done
Вероятно, это будет работать и с пробелами, если заменить нижнее подчеркивание на пробел. Я добавил часть с echo, чтобы вы могли протестировать и увидеть результаты.
Ответ или решение
Сплит строки по пробелам в ZSH: полное руководство
В операционных системах Unix и Linux часто возникает необходимость обрабатывать текстовые файлы, разбивая строки на отдельные слова или элементы. Здесь мы обсудим, как можно разбить строки по пробелам в Z Shell (ZSH), аналогично тому, как это делается в Bash.
Проблема и её решение
Перед нами стоит задача: из файла file.txt
извлечь каждую строку и разбить её на слова, используя пробел в качестве разделителя. Рассмотрим содержимое файла:
first line
second line
third line
В Bash для этой задачи мы можем использовать следующий код:
while IFS=' ' read -a args; do
echo "${args[0]}"
done < file.txt
Этот код читает файл построчно, разбивает каждую строку на массив args
, и затем выводит первый элемент (слово) каждой строки. Однако, если попробовать выполнить аналогичную команду в ZSH, мы столкнемся с ошибкой: read: bad option: -a
.
Зачем возникает ошибка?
В ZSH команда read
использует флаг -A
вместо -a
. В Bash индексация массивов начинается с нуля, тогда как в ZSH — с единицы. Это важно учитывать для корректной работы с данными.
Корректный код для ZSH
Для реализации аналогичного функционала в ZSH нам нужно использовать -A
для объявления массива. Также, поскольку индексация начинается с 1, мы укажем правильный индекс при обращении к элементам массива.
Вот как будет выглядеть код:
while IFS=' ' read -A args; do
echo "${args[1]}"
done < file.txt
Объяснение кода
-
while IFS=’ ‘: Устанавливает разделитель по умолчанию для
read
в пробел. Это позволяет разделять входные данные на слова. -
read -A args: Читает строку и разбивает её на массив
args
. -
echo "${args[1]}": Печатает первое слово (индекс 1) из массива
args
. Если нам нужно вывести все слова, используем цикл:
while IFS=' ' read -A args; do
for word in $args; do
echo "$word"
done
done < file.txt
Дополнительные примеры
Если вам необходимо разделить строку по другим разделителям, можно использовать следующий синтаксис:
var="слово1_слово2_слово3"
parts=(${(@s:_:)var})
for val in $parts; do
echo $val
done
В этом примере используется разделитель _
. Чтобы изменить разделитель на пробел, просто замените символ _
на пробел.
Заключение
Разделение строк по пробелам в ZSH требует некоторой адаптации подхода из Bash. Главные отличия заключаются в синтаксисе команды read
и индексации массивов. Понимание этих особенностей поможет вам эффективно обрабатывать текстовые данные в ZSH. Надеюсь, что данное руководство окажется полезным для вас в будущем!