Чтение файла построчно с присвоением значения переменной
У меня есть следующий файл .txt:
Marco
Paolo
Antonio
Я хочу прочитать его построчно и для каждой строки назначить значение строчки переменной. Предположим, моя переменная - это $name
, тогда последовательность действий будет следующей:
- Прочитать первую строку из файла.
- Присвоить
$name
значение "Marco". - Выполнить некоторые действия с
$name
. - Прочитать вторую строку из файла.
- Присвоить
$name
значение "Paolo".
Почему не удается реализовать этот процесс в Bash? Есть ли готовые решения для подобной задачи? Заранее благодарю за помощь!
5 ответ(ов)
Я рекомендую использовать флаг -r
для команды read
, который означает:
-r Не обрабатывать символ обратного слэша каким-либо особым образом. Рассматривать каждый
обратный слэш как часть входной строки.
Я цитирую из документации man 1 read
.
Еще один момент — передать имя файла в качестве аргумента.
Вот обновленный код:
#!/usr/bin/bash
filename="$1"
while read -r line; do
name="$line"
echo "Имя, прочитанное из файла - $name"
done < "$filename"
Таким образом, все символы, включая обратные слэши, будут правильно обработаны, и вы сможете легко считывать содержимое файла.
Вы можете использовать следующий шаблон Bash для чтения значений из файла по одному и их дальнейшей обработки:
while read name; do
# Выполните необходимые действия с $name
done < filename
Этот код открывает файл filename
и считывает содержимое построчно, сохраняя каждую строку в переменной name
. Вы можете заменить комментарий на любую необходимую обработку данных.
Ваш скрипт Bash считывает содержимое файла filename
построчно и выводит каждую строку в терминал. Вот пояснение:
#! /bin/bash
cat filename | while read LINE; do
echo $LINE
done
Пояснение:
#! /bin/bash
: Указывает, что скрипт должен выполняться с использованием интерпретатора Bash.cat filename
: Командаcat
считывает содержимое файлаfilename
.|
: Этот символ представляет собой конвейер, который передает вывод команды слева как вход для команды справа.while read LINE; do
: Циклwhile
используется для построчного чтения данных. Каждая строка изcat
будет присваиваться переменнойLINE
.echo $LINE
: Эта команда выводит значение переменнойLINE
, то есть текущую строку файла.
Замечание:
Использование cat
в данном случае не является необходимым. Можно упростить этот код, записав его так:
while read LINE; do
echo $LINE
done < filename
Это делает то же самое, но без использования cat
. Такой подход более эффективен, так как он избегает создания дополнительного процесса.
Ваш код считывает строки из файла, переданного в качестве аргумента, и выводит каждую строку с указанием источника (имени файла). Однако, важно помнить о том, что переменная окружения IFS
(Internal Field Separator - разделитель полей) играет значительную роль в разборе входных данных. Если вы измените значение IFS
, вы можете получить неожиданные результаты.
Вот ваш код с подробным пояснением:
filename=$1 # Получаем имя файла из первого аргумента скрипта
IFS=$'\n' # Устанавливаем IFS на новую строку, чтобы правильно разделять строки
for next in `cat $filename`; do # Цикл по всем строкам файла
echo "$next read from $filename" # Выводим текущую строку и имя файла
done
exit 0 # Успешное завершение скрипта
Если вы измените IFS
на что-то другое (например, пробелы или символы табуляции), это может привести к тому, что строки будут разделяться по другим критериям, и вы получите непредсказуемые результаты. Например, если в строке содержится пробел и вы установите IFS
в пробел, то эта строка будет разбита на несколько частей.
Чтобы избежать проблем, рекомендуется возвращать IFS
к его начальному значению после завершения работы с файлом, например:
OLDIFS=$IFS # Сохраняем старое значение IFS
IFS=$'\n' # Устанавливаем новый разделитель
# Ваш код...
IFS=$OLDIFS # Восстанавливаем старое значение IFS
Это поможет гарантировать, что влияние на IFS
будет локальным, и остальная часть вашего скрипта не будет затронута.
Многие пользователи публиковали решения, которые избыточно оптимизированы. Я не считаю их неправильными, но скромно полагаю, что менее оптимизированное решение будет более желательным, чтобы всем было проще понять, как оно работает. Вот мое предложение:
#!/bin/bash
#
# Эта программа читает строки из файла.
#
end_of_file=0
while [[ $end_of_file == 0 ]]; do
read -r line
# последний статус выхода является
# индикатором конца файла
end_of_file=$?
echo $line
done < "$1"
Это решение читается проще и дает ясное представление о том, как работает цикл чтения строк из файла.
Извлечение имени файла и расширения в Bash
Как изменить цвет вывода echo в Linux
Как сделать паузу в shell-скрипте на одну секунду перед продолжением?
Как работает "cat << EOF" в bash?
Передача параметров в функцию Bash