У меня есть следующий файл .txt:
Marco
Paolo
Antonio
Я хочу читать это построчно, и для каждой строки я хочу назначить строковое значение .txt переменной. Предположим, моя переменная $name
, поток:
$name
= "Марко"$name
$name
= "Паоло"Следующий (сохранить как rr.sh
) читает файл, переданный в качестве аргумента, строкой за строкой:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
done < "$1"
Пояснение:
IFS=''
(или IFS=
) предотвращает обрезку ведущего/конечного пробела.-r
предотвращает интерпретацию экранов обратной косой черты.|| [[ -n $line ]]
предотвращает игнорирование последней строки, если она не заканчивается на \n
(поскольку read
возвращает ненулевой код выхода, когда он встречает EOF).Запустите script следующим образом:
chmod +x rr.sh
./rr.sh filename.txt
....
ssh
без флага -n
фактически заставит вас выйти из цикла. Вероятно, для этого есть веская причина, но мне потребовалось некоторое время, чтобы понять, что приводило к сбою моего кода, прежде чем я это обнаружил.
Я рекомендую вам использовать флаг -r
для read
который обозначает:
-r Do not treat a backslash character in any special way. Consider each
backslash to be part of the input line.
Я цитирую man 1 read
.
Другое дело, взять имя файла в качестве аргумента.
Вот обновленный код:
#!/usr/bin/bash
filename="$1"
while read -r line; do
name="$line"
echo "Name read from file - $name"
done < "$filename"
Использование следующего шаблона Bash позволит вам читать по одному значению за раз из файла и обрабатывать его.
while read name; do
# Do what you want to $name
done < filename
read -r
, и вам нужно заключить в кавычки "$name"
.
#! /bin/bash
cat filename | while read LINE; do
echo $LINE
done
Enter
после последней строки), в противном случае последняя строка будет игнорироваться. По крайней мере, так случилось со мной.
Многие люди опубликовали решение, которое слишком оптимизировано. Я не думаю, что это неправильно, но я скромно думаю, что было бы желательно менее оптимизированное решение, чтобы позволить всем легко понять, как это работает. Вот мое предложение:
#!/bin/bash
#
# This program reads lines from a file.
#
end_of_file=0
while [[ $end_of_file == 0 ]]; do
read -r line
# the last exit status is the
# flag of the end of file
end_of_file=$?
echo $line
done < "$1"
Использование:
filename=$1
IFS=$'\n'
for next in 'cat $filename'; do
echo "$next read from $filename"
done
exit 0
Если вы установили IFS
другому, вы получите странные результаты.
Если вам нужно обработать как входной файл, так и пользовательский ввод (или что-либо еще из stdin), используйте следующее решение:
#!/bin/bash
exec 3<"$1"
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
read -p "> $line (Press Enter to continue)"
done
На основании принятого ответа и учебника перенаправления bash-хакеров.
Здесь мы открываем дескриптор файла 3 для файла, переданного в качестве аргумента сценария, и говорим read
чтобы использовать этот дескриптор в качестве входных данных (-u 3
). Таким образом, мы оставляем дескриптор ввода по умолчанию (0), прикрепленный к терминалу или другому источнику ввода, способный считывать ввод пользователя.
Для правильной обработки ошибок:
#!/bin/bash
set -Ee
trap "echo error" EXIT
test -e ${FILENAME} || exit
while read -r line
do
echo ${line}
done < ${FILENAME}
Следующее просто распечатает содержимое файла:
cat $Path/FileName.txt
while read line;
do
echo $line
done
Я прочитал вопрос как:
", если я хочу прочитать файл, ожидая, как это сделать? Я хочу сделать это, потому что, когда я писал" выполнение некоторых задач с помощью $name ", я имел в виду, что мои задачи - это команды."
Прочитайте файл из самого ожидаемого:
yourExpectScript:
#!/usr/bin/expect
# Pass in filename from command line
set filename [ lindex $argv 0 ]
# Assumption: file in the same directory
set inFile [ open $filename r ]
while { ! [ eof $inFile ] } {
set line [ gets $inFile ]
# You could set name directly.
set name $line
# Do other expect stuff with $name ...
puts " Name: $name"
}
close $inFile
Затем назовите его так:
yourExpectScript file_with_names.txt
expect
расширяется), который очень не bash.