seq
seq 10
运行一下就知道了,和
python
的range
一样
参数 | 含义 | 作用 |
---|---|---|
start |
序列起始 | 定义起始 |
end |
序列结束 | 定义结束 |
step |
步进 | 序列间隔 |
- 顺序
两者参数顺序相同。
单个参数时,表示的是
end
。两个参数时,表示的是
(start, end)
。三个参数时,表示的是
(start, step, end)
。
- 首尾
参数 seq
range
start
默认从 1
开始默认从 0
开始end
默认包含 默认不包含
到end -step
- 步进
两者一致。
# 1,3,5,7,9 seq 1 2 9 # 1,2,3,4,5,6,7,8,9 seq 9 seq 1 9
- 简略
如果不指定
step
,用{start..end}
更加方便。
seq
{}
start
- seq start end
{start..end}
seq start step end
{start..end..step}
{}
也不仅是seq
,它能够自动打开。之前说过的
mkdir {a,b}_{c,d}
就是如此。
for
模式
for var in vars;
do
statements
...
done
遍历
- 枚举
#!/bin/bash
for var in 1 2 3 4 5;
do
echo $var
done
- 序列
#!/bin/bash
for var in {1..9};
do
echo $var
done
echo "--------------------"
for var in `seq 9 -1 1`;
do
echo $var
done
- 命令
#!/bin/bash
for dir in `ls /etc/`;
do
echo $dir
done
- 路径
#!/bin/bash
for dir in /etc/*;
do
echo $dir
done
分隔
- 参数
#!/bin/bash
for param in $*;
do
echo $param
done
- 字符
#!/bin/bash
vars="a b c d e f g"
for var in $vars;
do
echo $var
done
- 自定
#!/bin/bash
OLD_IFS=$IFS
IFS=";"
vars="a;b;c;d;e;f;g"
for var in $vars;
do
echo $var
done
IFS=$OLD_IFS
通过环境变量
IFS
进行字符分隔,然后遍历。命令结果的遍历可以理解为
IFS=\n
的结果,不过细节不同。我们不得不熟悉
IFS
,因为有些时候我们需要指定分隔符,有时候却要避免。#!/bin/bash for line in `ls -lhi /etc`; do echo $line done
你会发现结果和你所想不太一致,因为
IFS
默认。
#!/bin/bash OLD_IFS=$IFS $IFS=";" for line in `ls -lhi /etc/`; do echo $line done IFS=$OLD_IFS
这样就
ok
了,当然,也可以当做split
进行使用。#!/bin/bash OLD_IFS=$IFS IFS=$2 for part in $1; do echo $part done IFS=$OLD_IFS
定界
#!/bin/bash
for((i=1;i<10;i++));
do
echo $i
done
- 界限
前面的都是枚举的遍历,没有所谓的动态边界。
(())
的for
,更贴合我们的代码习惯,也引入了条件限制。
while
模式
while expression;
do
statement
...
done
条件
#!/bin/bash
i=10
while((i-->0));
do
echo $i
done
continue
#!/bin/bash
i=10
while((i-->0));
do
if ((i%2==0));then
continue
fi
echo $i
done
break
#!/bin/bash
i=0
while((1));do
if ((i>=100));then
break
else
((i+=1))
fi
if ((i%2==0));then
continue
fi
echo $i
done
(())
对于
()
、(())
、[]
、[[]]
,都会感觉到模棱两可。借助
$(($A+$B))
或许可见一斑。首先,得明白第一个
$
的含义,总结起来,$
就是用来取变量名所存储的值的。也就是说,
(($A+$B))
返回的不过是一个变量,好比方法,不过是匿名的。
(())
和[[]]
都是脚本开的子进程,然后子进程进行执行。更主要的是
#!/bin/bash a=1 b=2 echo $(($a+$b)) echo $((a+b))
输出结果是一致的,为什么。
更多的我暂时也说不出,但是,明白的一点就是,我们可以不再那么繁琐。
翻译一下所谓的
$(($a+$b))
,就是$((1+2))
。也就是说,在
(())
内部,我们所使用的,是进一步的操作。直接的数值就是数值,直接的变量就是变量,
(())
进行数值计算,[[]]
进行字符的计算。而且,
++
,--
等操作可以直接进行。在
(())
中,就好比了高级语言的编程。所以,要跳出
$(($a+$b))
的陷阱,也不要在(())
中继续$
的操作。因为直接计算
1+2
是必定可以的,但是1+=2
是明显的错误。
shell
中的所谓变量,和高级语言中的变量差异不小,在(())
中的是高级语言计算。
until
模式
until expression;do
statement
...
done
例子
#!/bin/bash
i=0
until((i++>100));
do
if ((i%2 ==0));then
continue
fi
echo $i
done
在
(())
中尽情施展吧,高级语言可不是难事。
while
是满足expression
然后执行statement
。
unitl
是执行statement
直到满足expresstion
。简而言之,一个满足才行动,一个不满足才行动。
脚本
sum
#!/bin/bash
sum=0
for value in $*;do
((sum+=value))
done
echo "sum : $sum"
其中的
((sum += value))
也可以换成(( sum += $value))
。不过是变量运算变成了直接的手动数值加减。
但是绝对不能
$sum
,因为sum
必须保证是变量,普通数值不具备存储功能。
gfind
#!/bin/bash
if [ -d $1 ];then
dir=$1/*
else
dir=$1
fi
for file in $dir;do
if [ -d $file ];then
./find $file $2
else
line=`cat $file -n | grep $2 | sed -r 's/^ +//g' |sed -r 's/^([0-9]+).*$/\1/'`
fi
if (( line != 0 ));then
echo $file $line `sed -n "${line}p" $file `
fi
done
在指定目录下,根据文件内容查文件。
输出
文件名
,行号
,行内容
。对于脚本而言,循环的作用就是把单操作扩展到其他对象上。
不仅是数据,文件,或者更多。
把单次的重复简略化,批处理更快捷。