如何用Shell脚本的while循环同时读取两个文件的第n行?
同时读取两个文件对应行的Shell脚本实现
问题描述
现有同目录下的name.txt和extensionv2.txt两个文件,行数相近,需要通过while循环同时读取两个文件的第n行,分别存入ex1和nm变量中。原脚本使用sed命令无法正确获取指定行,寻求可行的Shell脚本方案。
原脚本代码:
m=$(wc -l name.txt) echo "m = $m" t5="name.txt" j=${m//$t5/} echo "j = $j" k=1 while [ $j -ge $k ] do echo $j ex1=$(sed -n "$j{p;m}" extensionv2.txt) # Print a variable line in file nm=$(sed -n "$j{p;m}" name.txt) echo "ex1 = $ex1" echo "nm = $nm" #v=echo "'$nm.$ex1'" j=$(($j-1)) done
另外尝试过单文件读取的代码,但不知如何整合:
input="name.txt" while IFS= read -r line do echo "$line" done < "$input"
原脚本问题分析
- 行数获取不可靠:
wc -l name.txt的输出格式为行数 文件名,用字符串替换${m//$t5/}提取行数的方式容错性差(比如文件名含空格时会出错),正确姿势是用m=$(wc -l < name.txt)直接获取纯行数。 - sed命令使用错误:
sed -n "$j{p;m}"中的m命令是打印模式空间并清空,此处只需获取指定行,应改为sed -n "$j p"或sed -n "$j{p;q}"。 - 效率低下:每次循环都用
sed从头读取整个文件,大文件场景下会大幅拖慢脚本运行速度。
解决方案
推荐两种高效可靠的实现方式:
方法一:文件描述符并行读取
#!/bin/bash # 为两个文件打开独立的文件描述符 exec 3< "name.txt" exec 4< "extensionv2.txt" # 循环读取,直到其中一个文件读取完毕 while IFS= read -r nm <&3 && IFS= read -r ex1 <&4; do echo "nm = $nm" echo "ex1 = $ex1" # 这里可添加业务逻辑,比如拼接文件名:v="$nm.$ex1" done # 关闭文件描述符 exec 3<&- exec 4<&-
方法二:paste命令合并后读取
#!/bin/bash # 用paste将两个文件的对应行以制表符合并,再逐行拆分变量 paste "name.txt" "extensionv2.txt" | while IFS=$'\t' read -r nm ex1; do echo "nm = $nm" echo "ex1 = $ex1" # 业务逻辑处理,如v="$nm.$ex1" done
说明
- 方法一通过文件描述符直接并行读取,避免重复扫描文件,效率更高,且能自动处理行数不一致的情况(任一文件读完即终止循环)。
- 方法二利用
paste先合并对应行,再拆分变量,代码更简洁,适合行数完全一致的场景。
内容的提问来源于stack exchange,提问作者PBS
相关产品推荐
相关产品推荐

