Прочитать строку строки по строке, присваивая значение переменной

У меня есть следующий файл .txt:

Marco
Paolo
Antonio

Я хочу читать это построчно, и для каждой строки я хочу назначить строковое значение .txt переменной. Предположим, моя переменная $name, поток:

  • Читать первую строку из файла
  • Назначьте $name= "Марко"
  • Выполните несколько задач с $name
  • Читать вторую строку из файла
  • Назначьте $name= "Паоло"

Ответ 1

Следующее читает файл, передаваемый в качестве аргумента построчно:

#!/bin/bash
while IFS= read -r line; do
    echo "Text read from file: $line"
done < "$1"

Это стандартная форма для чтения строк из файла в цикле. Объяснение:

  • IFS= (или IFS='') предотвращает обрезание начальных/конечных пробелов.
  • -r предотвращает интерпретацию обратной косой черты.

Если вышеперечисленное сохранено в сценарии с именем файла для readfile, его можно запустить следующим образом:

chmod +x readfile
./readfile filename.txt

Если файл не является стандартным текстовым файлом POSIX (= не завершается символом новой строки), цикл может быть изменен для обработки завершающих частичных строк:

while IFS= read -r line || [[ -n "$line" ]]; do
    echo "Text read from file: $line"
done < "$1"

Здесь, || [[ -n $line ]] || [[ -n $line ]] предотвращает игнорирование последней строки, если она не заканчивается на \n (так как read возвращает ненулевой код выхода при обнаружении EOF).

Если команды внутри цикла также читаются из стандартного ввода, дескриптор файла, используемый для read может быть изменен на что-то другое (избегайте стандартных файловых дескрипторов), например:

while IFS= read -r -u3 line; do
    echo "Text read from file: $line"
done 3< "$1"

(Оболочки не Bash могут не знать read -u3; вместо этого используйте read <&3)

Ответ 2

Я рекомендую вам использовать флаг -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"

Ответ 3

Использование следующего шаблона Bash позволит вам читать по одному значению за раз из файла и обрабатывать его.

while read name; do
    # Do what you want to $name
done < filename

Ответ 4

#! /bin/bash
cat filename | while read LINE; do
    echo $LINE
done

Ответ 5

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

#!/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"

Ответ 6

Использование:

filename=$1
IFS=$'\n'
for next in 'cat $filename'; do
    echo "$next read from $filename" 
done
exit 0

Если вы установили IFS другому, вы получите странные результаты.

Ответ 7

Если вам нужно обработать как входной файл, так и пользовательский ввод (или что-либо еще из 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), прикрепленный к терминалу или другому источнику ввода, способный считывать ввод пользователя.

Ответ 8

Для правильной обработки ошибок:

#!/bin/bash

set -Ee    
trap "echo error" EXIT    
test -e ${FILENAME} || exit
while read -r line
do
    echo ${line}
done < ${FILENAME}

Ответ 9

Использовать инструмент IFS (внутренний разделитель полей) в bash, определяет символ, используемый для разделения строк на токены, по умолчанию включает в себя < tab >/< space >/< newLine >

Шаг 1: Загрузите данные файла и вставьте в список:

# declaring array list and index iterator
declare -a array=()
i=0

# reading file in row mode, insert each line into array
while IFS= read -r line; do
    array[i]=$line
    let "i++"
    # reading from file path
done < "<yourFullFilePath>"

шаг 2: теперь повторяем и выводим вывод:

for line in "${array[@]}"
  do
    echo "$line"
  done

echo конкретный индекс в массиве: доступ к переменной в массиве:

echo "${array[0]}"

Ответ 10

Следующее просто распечатает содержимое файла:

cat $Path/FileName.txt

while read line;
do
echo $line     
done

Ответ 11

Я прочитал вопрос как:

", если я хочу прочитать файл, ожидая, как это сделать? Я хочу сделать это, потому что, когда я писал" выполнение некоторых задач с помощью $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