Bash case语句中变量赋值后无法外部调用问题求助
问题:Bash循环内赋值的变量无法在循环外部访问
输入文件IPlist.csv仅一行内容:
30.xx.xx.xx,Bill
测试代码:
#!/bin/bash MyList=IPlist.csv while IFS=, read -r myIP UserName _ do case $UserName in Tom) echo "Case is Tom and the IP address is $myIP..." UserName="Tom" echo "Username is $UserName" ;; Bill) echo "Case is Bill and the IP address is $myIP..." UserName="Bill" echo "Username is $UserName" ;; *) echo "Case is incorrect..." echo "Exiting line read...." esac done <$MyList echo "$UserName"
期望输出:
Tom@hostname ~ $ ./MyTest3.sh Case is Bill and the IP address is 30.xx.xx.xx... Username is Bill Bill
实际输出:
Tom@hostname ~ $ ./MyTest3.sh Case is Bill and the IP address is 30.xx.xx.xx... Username is Bill
补充场景:最终需处理16000行逗号分隔文件,根据用户名执行snmpget操作获取snmpv3 engineID,要求方案适配该场景。
解决方案
问题根源
Bash中,当使用done < $MyList这种重定向方式时,while read循环会在子shell中运行,循环内对变量的修改不会同步到父shell环境,因此循环外部的echo "$UserName"无法获取到循环内赋值的变量值。
适配大文件的解决方法
方法1:使用进程替换让循环在当前shell执行
将重定向改为进程替换< <(cat $MyList),这样循环会在当前shell进程中运行,变量修改会被保留:
#!/bin/bash MyList=IPlist.csv while IFS=, read -r myIP UserName _ do case $UserName in Tom) echo "Case is Tom and the IP address is $myIP..." echo "Username is $UserName" ;; Bill) echo "Case is Bill and the IP address is $myIP..." echo "Username is $UserName" ;; *) echo "Case is incorrect..." echo "Exiting line read...." esac done < <(cat "$MyList") # 修改为进程替换 echo "$UserName"
方法2:将变量结果写入临时文件(适合保留多组结果的场景)
如果需要处理多行数据并保留每个用户的相关变量,可以将循环内的结果写入临时文件,后续读取:
#!/bin/bash MyList=IPlist.csv temp_file=$(mktemp) while IFS=, read -r myIP UserName _ do case $UserName in Tom|Bill) echo "Case is $UserName and the IP address is $myIP..." echo "Username is $UserName" # 将需保留的变量写入临时文件 echo "$UserName,$myIP" >> "$temp_file" ;; *) echo "Case is incorrect..." echo "Exiting line read...." esac done < "$MyList" # 读取临时文件的最后一行用户名(示例) last_user=$(tail -n1 "$temp_file" | cut -d, -f1) echo "$last_user" # 清理临时文件 rm "$temp_file"
针对16000行大文件的优化建议
- 方法1的进程替换效率较高,无需额外IO操作,适合单变量传递的场景;
- 若需对每个用户执行snmpget,直接在循环内完成操作是更高效的方式,减少变量传递的复杂度:
#!/bin/bash MyList=IPlist.csv while IFS=, read -r myIP UserName _ do case $UserName in Tom) # 针对Tom执行snmpget操作 snmpget -v3 -u Tom "$myIP" <目标OID> ;; Bill) # 针对Bill执行snmpget操作 snmpget -v3 -u Bill "$myIP" <目标OID> ;; *) echo "Unknown user $UserName for IP $myIP" esac done < <(cat "$MyList")
内容的提问来源于stack exchange,提问作者Rovernut
相关产品推荐
相关产品推荐

