Shell while循环语句中的陷阱
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell while循环语句中的陷阱相关的知识,希望对你有一定的参考价值。
参考技术A 我们经常使用while来循环读取文件的每一行,并用文件中的数据对变量赋值,典型写法如下结果显示两次value打印都是0,循环中的赋值没有起作用。问题出在这种while写法上,cat file | while read 的意思是: 使用 cat 命令查看文件,通过管道将结果传送给包含 read 命令的 while 命令,会每次读取文件中的一行文本,传给read后的参数,参数可以为多个,默认以空格分隔,当文件中没有可读取的文本时,read 命令将以非零状态退出。 这就意味着while循环中的程序实际上是在一个子进程中执行的,当前进程通过管道将文件内容传递到子进程。循环体中的value并非是外部定义的value,在循环体中对value赋值自然也不能改变外部value的值。
解决方法是换一种读文件的方法,将循环体放到当前进程中执行。
cat file | while read 是一种很不友好的写法,虽然最常用,但是效果最差。 推荐使用以上<data.txt的读文件方法。
用上述cat | while写法读文件时还可能碰见另一个问题:读不到文件的最后一行。如data.txt文件的内容如下
用上述cat | while写法则可能只会读到222,最后一行333被忽视了。上文已经说到while如果判断没有可读取的文本时就会退出,while判断是否到达文件末尾是识别文件结束符EOF。文件最后一行之后如果没有换行符\n,则read读取最后一行时遇到EOF,循环即终止。此时虽在内存有最后一行,但程序已经没有机会再处理此行内容。
知道原因了就可以解决这个问题,权宜之计是在最后一行的后面再换个行。治标的方法是用dos2unix将文件格式转换为Unix,因为缺少换行符一般是由于Windows文件传到Linux没有转换格式。
Linux命令行真的是宝藏,功能丰富,用法多样。如果Linux的生态圈能够更发达一点,说不定以后Linux
会是家庭电脑的主流操作系统。
Shell脚本------循环语句(for,while,until循环语句)
目录
一.echo语句
echo -n 表示不换行输出
echo -e 输出转义字符,将转义后的内容输出到屏幕上
✪常用的转义字符
\\b :转义后相当于按退格键,但前提是“\\b
”后面存在字符;“\\b
”表示删除前一个字符,“\\b\\b
”表示删除前两个字符。
\\c:不换行输出,在“\\c
”后面不存在字符的情况下,作用相当于echo -n
,但是当“\\c
”后面仍然存在字符时,“\\c
”后面的字符将不会被输出。
\\n:换行,被输出的字符从“\\n
”处开始另起一行。
\\f:换行,但是换行后的新行的开头位置连接着上一行的行尾;\\v
与\\f
相同。
\\t 转义后表示插入tab
,即横向制表符
\\r:光标移至行首,但不换行,相当于使用“\\r
”以后得字符覆盖“\\r
”之前同等长度的字符;但是当“\\r
”后面不存在任何字符时,“\\r”前面的字符不会被覆盖。
\\:表示插入“\\
”本身。
✪示例
1.通过输出转义子符实现磁盘分区
✪截取字符串
i=`echo "11,22,33, 44"`
echo ${i%,*}
11,22, 33
//从最后倒数到最短的匹配部分(用%)后面的逗号的地方被删除
echo ${i%%,*}
l1
//从最后倒数到最长的匹配部分(用%%)后面的逗号的地方都被删除
echo ${i#*, }
22,33, 44
//从开头到最短的匹配部分(用#)后面的逗号的地方被删除
echo ${i##*,}
44
//从开头到最长的匹配部分(用##)后面的逗号的地方被删除
i=`echo “1234567890”`
echo ${i:3:4}
4567
//从第3位开始截取,第一位为0,截取4位,中间用“:”隔开
二.循环语句
1.for循环语句
读取不同的变量值,用来逐个执行同一组命令
for 变量名 in 取值列表 for 收件人 in 邮件地址列表
do do
命令序列 发送邮件
done done
✪for循环的三种表达方式
❉第一种
❉第二种
❉第三种
✪示例
❉1.批量添加用户
用户名存放在user.txt文件中,每行一个
初始密码均为666
#!/bin/bash
USER=$(cat /scripts/user.txt)
for i in $USER
do
useradd $i
echo 666 | passwd --stdin $i &> /dev/null
done
sh user.sh
❉2.根据IP地址检查主机状态
IP地址存放在ipadds.txt文件中,每行一个
使用ping命令检测各主机的连通性
vim ip.sh
#!/bin/bash
IP=`cat /script/ipadds.txt`
for i in $IP
do
ping -c 5 -i 0.2 -w 2 $i &> /dev/null
if [ $? -eq 0 ]
then
echo "$i主机存活"
else
echo "$i主机不存活"
fi
done
sh ip.sh
2.while语句的结构
重复测试某个条件,只要条件成立则反复执行
while 条件测试操作
do
命令序列
done
✪示例
❉1.批量添加用户
用户名称以stu开头,按数字顺序进行编号
一共添加20个用户,即stu1,stu2,……,stu20
初始密码均为666
vim 2.sh
#!/bin/bash
a=1
while [ $a -le 20]
do
useradd stu$a
echo 666 | passwd --stdin stu$a
let a++
done
sh 2.sh
❉2.猜商品价格
通过变量RANDOM获得随机数
提示用户猜测并记录次数,猜中后退出循环
vim 3.sh
#!/bin/bash
ran=$[ $RANDOM % 1000 ]
a=1
b=0
while [ $a -lt 2 ]
do
read -p "请输入你猜的价格(1-999):" cai
if [ $cai -eq $ran ]
then
echo "恭喜你你猜对了!"
let b++
let a++
elif [ $cai -gt $ran ]
then
echo "你猜高了!"
let b++
elif [ $cai -lt $ran ]
then
echo "你猜低了!"
let b++
fi
done
3.until语句
重复测试某个条件,只要条件不成立则反复执行
until 条件测试操作
do
命令序列
done
✪示例
计算1-50的和值
通过循环累加的方式计算1-50的和值
三.终止循环
1.break跳出单个循环
#!/bin/bash
for ((a=1;a<=5;a++))
do
echo "外循环--------:a=$a"
for ((b=1;b<=5 ;b++))
do
if [ $b -eq 3 ]
then
break
fi
echo -e "\\t内循环-------:b=$b" \\t为横向制表符
done
done
2.continue中止某次循环中的命令,但不会完全中止整个命令
#!/bin/bash
for ((a=1;a<=5;a++))
do
echo "外循环--------:a=$a"
for ((b=1;b<=5 ;b++))
do
if [ $b -eq 3 ]
then
continue
fi
echo -e "\\t内循环-------:b=$b"
done
done
示例
用户输入密码,脚本判断密码是否正确,输入正确提示提示正确信息,连续输错3次则报警
#!/bin/bash
ma=123456
for ((i=1;i<=3;i++))
do
read -p "请输入密码:" a
if [ $a -eq $ma ]
then
echo "密码输入正确!"
exit
else
echo "密码输入错误,请再次输入"
fi
done
echo "警告,密码错误3次。"
四.IFS字段分隔符
默认包含空格( ),制表符(\\t) ,换行符(\\n)
set | grep IFS 查看IFS字段分隔符
示例
输出环境变量PATH所包含的所有目录以及其中的所有可执行文件
#!/bin/bash
#PATH所包含的所有目录以及其中的所有可执行文件
dz=$IFS
IFS=$IFS:
for i in $(echo $PATH)
do
echo "PATH所包含的目录:" $i
for a in $i/*
do
if [ -x $a ]
then
echo "其中的可执行文件:" $a
fi
done
done
IFS=$dz
以上是关于Shell while循环语句中的陷阱的主要内容,如果未能解决你的问题,请参考以下文章
Shell编程Shell中for循环while循环until循环语句
Shell脚本------循环语句(for,while,until循环语句)