如何解决Bash中while read line循环调用grep处理文本时的空输出与文件名异常问题
解决Shell脚本匹配空输出+文件名乱码问题
你的问题其实是两个小坑导致的:Windows换行符污染,再加脚本里的变量赋值错误,咱们一步步搞定:
问题根源拆解
- 换行符搞的鬼:你的
capital_names.txt是Windows格式的文件,每行末尾都藏着一个回车符(\r,就是你看到的$'\r')。当read命令读行的时候,会把这个\r也塞进line变量里,结果grep ^$line实际是在找^Warsaw_\r这种开头的内容,而capital_info.txt里根本没有,自然输出空文件;同时文件名里混进了\r,就变成了乱码的样子。 - 变量赋值写错了:脚本里的
$outp="output"是错误的,Shell里给变量赋值不能在变量名前面加$,正确写法是outp="output"。
分步解决方案
第一步:修复文本文件的换行符
先把capital_names.txt转换成Linux/Unix格式,去掉多余的\r:
- 如果你的系统有
dos2unix工具,直接跑这个命令就行:dos2unix capital_names.txt - 要是没有
dos2unix,用sed或者tr也能搞定:# 用sed原地修改原文件 sed -i 's/\r$//' capital_names.txt # 或者用tr生成一个修复好的新文件 tr -d '\r' < capital_names.txt > capital_names_fixed.txt
第二步:修正Shell脚本
调整变量赋值和读行逻辑,确保文件名和匹配都正确:
#!/bin/bash outp="_output.txt" # 这样拼出来的文件名就是你要的Warsaw_output.txt while IFS= read -r line; do # 用引号把变量包起来,避免特殊字符搞事情,同时正确拼接文件名 grep "^$line" capital_info.txt > "${line}${outp}" done < capital_names.txt
这里加了两个实用细节:
IFS= read -r line:IFS=防止读取时把行首行尾的空格吃掉,-r禁止read解析转义字符,保证读进来的行内容完全和原文件一致。"${line}${outp}":用大括号把变量名括起来,避免变量拼接时出现歧义(比如如果变量名后面跟着字母,Shell会认错变量)。
验证一下
你可以先手动测试,确认修复有效:
# 查看修复后的文件里有没有\r cat capital_names.txt | od -c | head # 测试grep能不能匹配到内容 grep "^Warsaw_" capital_info.txt
这样跑脚本之后,就能生成正确的Warsaw_output.txt、London_output.txt,内容也和你预期的一样啦。
内容的提问来源于stack exchange,提问作者duda13
相关产品推荐
相关产品推荐

