在子shell中设置和操作变量之后, 如果尝试在子shell作用域之外使用同名变量的话, 将会产生令人不快的结果.子shell和父shell看起来其实就是隔离的。
将echo的输出通过管道传递给read命令可能会产生不可预料的结果. 在这种情况下, read命令的行为就好像它在子shell中运行一样. 可以使用set命令来代替。
通过管道将输出传递到任何循环中, 都会引起类似的问题.
for f in $(find $HOME -type f -atime +30 -size 100k) # 这里没使用管道
另一种方法:将脚本中读取变量的部分放到一个代码块中, 这样一来, 它们就能在相同的子shell中共享了.
find $HOME -type f -atime +30 -size 100k | {
foundone=false
while read f
....
}
>>操作符可以在文件末尾添加内容. 如果你想在文件的头部添加内容怎么办, 难道要粘贴到文件头?
file=data.txt title="***This is the title line of data text file***"
echo $title | cat - $file >$file.new
将你最喜欢的变量定义和函数实现都放到一个文件中. 在你需要的时候, 通过使用点(.)命令,或者source命令, 来将这些"库文件""包含"到脚本中.
函数的返回值严格限制在0 - 255之间. 使用全局变量或者其他方法来代替函数返回值, 通常都很容易产生问题. 从函数中, 返回一个值到脚本主体的另一个办法是, 将这个"返回值"写入到stdout(通常都使用echo命令), 然后将其赋值给一个变量. 这种做法其实就是命令替换的一个变种.
返回多个值的技巧:将每个计算出来的结果输出到stdout, 并以空格分隔.
将数组传递给函数的技术, 然后"返回"一个数组给脚本的主体.使用命令替换将数组中的所有元素(元素之间用空格分隔)赋值给一个变量, 这样就可以将数组传递到函数中了. 之前提到过一种返回值的策略, 就是将要从函数中返回的内容, 用echo命令输出出来, 然后使用命令替换或者( ... )操作符, 将函数的输出(也就是我们想要得返回值)保存到一个变量中. 如果我们想让函数"返回"数组, 当然也可以使用这种策略.
Pass_Array (){
passed_array=( `echo "$1"` )
echo "${passed_array[@]}
}
original_array=( element1 element2 element3 element4 element5 )
argument=`echo ${original_array[@]}`
returned_array=( `Pass_Array "$argument"` )
利用双括号结构, 就可以让我们使用C风格的语法, 在for循环和while循环中, 设置或者增加变量.
一项很有用的技术是, 重复地将一个过滤器的输出(通过管道)传递给这个相同的过滤器, 但是这两次使用不同的参数和选项. 尤其是tr和grep, 非常适合于这种情况.
在错误的情况下, if-grep test可能不会返回期望的结果, 因为出错文本是输出到stderr上, 而不是stdout.将stderr重定向到stdout上, 就可以解决这个问题
if ls -l nonexistent_filename 2>&1 | grep -q 'No such file ordirectory'