我有以下.txt文件:
Marco
Paolo
Antonio
我想逐行阅读它,并且我想为每行分配一个.txt行值给一个变量。假设我的变量是$name
,流程是:
- 从文件中读取第一行
- 分配
$name
=“马可” - 做一些任务
$name
- 从文件中读取第二行
- 分配
$name
=“ Paolo”
我有以下.txt文件:
Marco
Paolo
Antonio
我想逐行阅读它,并且我想为每行分配一个.txt行值给一个变量。假设我的变量是$name
,流程是:
$name
=“马可”$name
$name
=“ Paolo”Answers:
以下内容逐行读取作为参数传递的文件:
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"
如果以上内容保存到具有filename的脚本中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 ]]
如果最后一行没有以a结尾\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
改用。)
ssh
没有该-n
标志将有效地导致您退出循环。可能有一个很好的理由,但是我花了一段时间才找出导致代码失败的原因,然后才发现这一点。
ffmpeg
食用了stdin。添加</dev/null
到您的ffmpeg
行中将无法执行此操作,或者将备用FD用于循环。这种“备用FD”方法看起来像while IFS='' read -r line <&3 || [[ -n "$line" ]]; do ...; done 3<"$1"
。
.sh
扩展。UNIX上的可执行文件通常根本不具有扩展名(您不运行ls.elf
),并且具有bash shebang(以及仅限bash的工具,例如[[ ]]
)和扩展,这意味着POSIX sh兼容性在内部是矛盾的。
我鼓励您使用代表以下内容的-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"
sh
,不是bash
; || [[ -n "$line" ]]
在接受的答案中的语法中使用的扩展测试命令是bashism。就是说,该语法实际上具有相关的含义:即使没有换行符,它也会使循环在输入文件的最后一行继续。如果您想以符合POSIX的方式进行操作,则可以|| [ -n "$line" ]
使用[
而不是[[
。
IFS=
为read
防止修剪空白。
使用以下Bash模板应该可以让您一次从文件中读取一个值并进行处理。
while read name; do
# Do what you want to $name
done < filename
*
。
#! /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
不同,您将得到奇怪的结果。
*
在一行中包含单个文件的文件?无论如何,这是一种反模式。不要读取带有for的行。
read
方法是社区共识中的最佳实践方法。您在注释中提到的警告是一种适用于您的循环运行ffmpeg
从stdin读取的命令(例如)的方法,该问题通过使用非stdin FD循环或重定向此类命令的输入来轻松解决。相比之下,要解决for
-loop方法中的全局错误,则意味着要更改(然后需要撤消)shell全局设置。
for
循环方法,你在这里使用的手段,所有的内容在之前的循环可以开始执行全部被读取,使其完全无法使用,如果你遍历千兆字节的数据,即使你有残疾球 的while read
循环需要在同一时间不超过一行的数据存储,这意味着它可以开始执行,而子过程产生内容仍在运行(从而是用于流目的可用),并且还具有有界的内存消耗。
while
基于偶数的方法似乎也存在*字符问题。请参阅上面接受的答案的注释。但是,不反对在文件上重复进行反模式辩论。
如果您需要同时处理输入文件和用户输入(或stdin的其他任何内容),请使用以下解决方案:
#!/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),它能够读取用户输入。
以下将只打印出文件内容:
cat $Path/FileName.txt
while read line;
do
echo $line
done
在bash中使用IFS(内部字段分隔符)工具,定义用于将行分隔为标记的字符,默认情况下包括< 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 "${array[0]}"