我有一个如下的 .txt 文件:
Marco
Paolo
Antonio
我想逐行读取文件,并为每行分配一个 .txt 行值到一个变量中。假设我的变量是 $name
,流程如下:
- 从文件中读取第一行
- 分配
$name
= "Marco" - 对
$name
执行一些任务 - 从文件中读取第二行
- 分配
$name
= "Paolo"
我有一个如下的 .txt 文件:
Marco
Paolo
Antonio
我想逐行读取文件,并为每行分配一个 .txt 行值到一个变量中。假设我的变量是 $name
,流程如下:
$name
= "Marco"$name
执行一些任务$name
= "Paolo"while IFS= read -r line; do
echo "Text read from file: $line"
done < my_filename.txt
这是从文件中循环读取行的标准形式。解释如下:
IFS=
(或IFS=''
)可以防止前导/尾随空格被修剪。-r
可以防止反斜杠转义字符被解释。或者您可以将其放入bash文件助手脚本中,示例内容如下:
#!/bin/bash
while IFS= read -r line; do
echo "Text read from file: $line"
done < "$1"
readfile
的脚本,则可以按以下方式运行:chmod +x readfile
./readfile filename.txt
while IFS= read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
done < "$1"
|| [[ -n $line ]]
防止最后一行没有以 \n
结尾而被忽略(因为当遇到 EOF 时,read
返回非零退出码)。read
使用的文件描述符更改为其他值(避免使用 standard file descriptors),例如:while IFS= read -r -u3 line; do
echo "Text read from file: $line"
done 3< "$1"
read -u3
;请使用read <&3
代替。)-n
标志的ssh
会有效地使您退出循环。可能有很好的原因解释这种情况,但在我发现此问题导致我的代码失败之前,我花了一段时间才找到它。 - Alexffmpeg
占用了stdin所导致的。在你的ffmpeg
命令中添加</dev/null
可以解决问题,或者使用循环的其他文件描述符。使用“其他文件描述符”的方法看起来像是while IFS='' read -r line <&3 || [[ -n "$line" ]]; do ...; done 3<"$1"
。 - Charles Duffy.sh
后缀的建议方面,咕噜声,在UNIX系统中,可执行文件通常根本没有扩展名(例如你并不运行ls.elf
),因此在脚本文件中既使用bash shebang(#!/bin/bash
)和bash专用工具(例如[[ ]]
),又添加扩展名以暗示其与POSIX sh兼容是自相矛盾的。 - Charles Duffy我建议您在使用read
命令时使用-r
标志,该标志代表:
-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"
sh
而不是bash
。 在接受的答案中使用的扩展测试命令|| [[ -n "$line" ]]
是一种Bash语法。 也就是说,该语法实际上具有相关意义:即使输入文件的最后一行没有换行符,它也会导致循环继续进行。 如果要以符合POSIX标准的方式执行此操作,您需要使用|| [ -n "$line" ]
,其中使用[
而不是[[
。 - Charles DuffyIFS =
以供read
使用。 - Charles Duffy使用下面的Bash模板,可以让您逐个读取文件中的值并进行处理。
while read name; do
# Do what you want to $name
done < filename
*
的行的内容。 - Charles Duffy#! /bin/bash
cat filename | while read LINE; do
echo $LINE
done
Enter
键),否则最后一行将被忽略。至少这就是我的经历。 - Antônio Medeiros使用:
filename=$1
IFS=$'\n'
for next in `cat $filename`; do
echo "$next read from $filename"
done
exit 0
如果您已经不同地设置了IFS
,那么您将会得到奇怪的结果。许多人发布的解决方案过于优化。我不认为它是错误的,但我谦虚地认为一个不那么优化的解决方案将更加可取,以便让每个人都能轻松理解这是如何工作的。以下是我的建议:
#!/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"
如果您需要同时处理输入文件和用户输入(或来自标准输入的任何其他内容),请使用以下解决方案:
#!/bin/bash
exec 3<"$1"
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
read -p "> $line (Press Enter to continue)"
done
在这里,我们为作为脚本参数传递的文件打开文件描述符3,并告诉read
使用此描述符作为输入(-u 3
)。 因此,我们将默认的输入描述符(0)附加到终端或其他输入源,可以读取用户输入。
exec 3<&0
。 - Orwellophile为了正确处理错误:
#!/bin/bash
set -Ee
trap "echo error" EXIT
test -e ${FILENAME} || exit
while read -r line
do
echo ${line}
done < ${FILENAME}
# 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>"
:现在迭代并打印输出:
for line in "${array[@]}"
do
echo "$line"
done
在数组中输出特定索引:访问数组中的变量:
echo "${array[0]}"
array[i]="$line"
。 - ErikEarray[i++]=$line
without the need for let
- Jetchiselcat $Path/FileName.txt
while read line;
do
echo $line
done