相关关键词
- for 循环
- while 循环
- while循环内的变量在循环外失效
- 批量生成脚本
- 批量处理
适用背景
我们在Linux系统中经常会对文件批量处理或需要批量生产脚本和批量投递任务等,而Shell的常用循环有for和while,本文将展示for和while循环的示例脚本。
for
-
命令行模式
每个元素以空格分隔,在do后面接上运行脚本,如果有多行脚本用分号“;”代替换行,最后以done结尾。
for i in a b c ; do echo $i;done
-
多行模式
适合在脚本文本里写多行处理。
for i in a b c ;
do
echo $i
done
-
遍历文件模式
使用通配符模糊匹配文件,然后可以对匹配上的文件进行相关操作
for file in ./file*
do
echo $file
done
- 遍历数组模式
##先创建数组
arr=(a b c)
#遍历数组${arr[@]}也可以写成${arr[*]}
for i in ${arr[@]}
do
echo $i
done
while
-
条件判断模式
类似于if语句,使用[]操作符给定判定条件
n=1
while [ $n -le 3 ]
do
echo $n
let n++
done
-
命令行模式
上面的语句可以写成以下一行
n=1;while [ $n -le 3 ]; do echo $n;let n++; done
-
读入输入模式
适合写进文件进行操作,并且输入“quit”可以退出循环,不然会一直要求读入。
echo "Please enter a name!"
while read var
do
if [ "$var" = "quit" ]
then
break
fi
echo "Your name is ${var}."
done
-
遍历数组模式
U1S1,这种还不如用for循环。
arr=(a b c)
n=0
while [ $n -lt ${#arr[@]} ]
do
echo ${arr[$n]}
let n++
done
-
读入文件模式
这种模式特别好用,特别是对于需要传入多个参数批量生成脚本进行投递的时候,只需要传入一个文件就可以轻松批量处理。而且很适合有超过10个任务的时候,少于10个的任务存在数组一般就够了,但现在大数据时代都是几十个甚至上百个数据集需要批量跑任务,这个就很好用了。
以下面为例,我已经提前写好一个脚本叫test.R,这个脚本需要传入四个参数 ${name} ${inpath} ${prefix} $PWD($PWD可以自动获取当前目录路径,可以直接忽略),${name}是数据集名称,我把所有数据集的名称都放入一个txt格式的列表文件,例如datasets_list.txt,${inpath} 是数据集原始数据所在路径,例如/home/,${prefix}是本批次数据集的标签名称,例如batch1_0525,把下面的代码写进一个脚本例如test.sh,运行代码:
sh test.sh datasets_list.txt /home/ batch1_0525
inpath="$2"
prefix="$3"
#while 逐行读取文件
cat $1|while read line
do
#对读取的一行按制表符(\t)进行切分并存为一个数组arr,因此可以在输入文件传入多个参数,第一个元素是${arr[0]},第二个元素是${arr[1]},以此类推
arr=(${line//\\t/ })
name=${arr[0]}
echo "source ~/.bashrc;Rscript test.R ${name} ${inpath} ${prefix} $PWD" >> ${prefix}_run.sh
done
然后就可以生成batch1_0525_run.sh脚本文件,也就是批量生成脚本,之后可以根据这个脚本进行批量运行任务。
然而,上面的写法存在一个问题:在循环之外,变量${name}是没有内容的,也就是循环内的变量在循环外失效了。这是因为这种写法使用了管道符“|”,先使用cat打开了一个进程,之后再开启子进程进行循环,所以退出循环后循环进程已经关闭,里面的变量没有及时更新到当前进程,也就失效了。
换成下面这种写法可以解决这种问题:
inpath="$2"
prefix="$3"
while read line
do
arr=(${line//\\t/ })
name=${arr[0]}
echo "source ~/.bashrc;Rscript test.R ${name} ${inpath} ${prefix} $PWD" >> ${prefix}_run.sh
done < $1
小结与补充
Shell循环当然不只是for和while,还有until等等,但这两种循环已经满足绝大多数的需求了。while不仅可以重定向打开某个文件,还可以重定向输出到某个文件,但是后者几乎很少用到,但前者是真的好用,极力推荐。
网友评论