内部命令

下载文件可用wget -O file url(wget的的大写-O选项指定输出文件名,小写的-o指定日志文件名)或者 curl url > file ,curl url --silent -o new-filename (curl的大写-O选项见文件写入url相同的文件名,小写的-o指定文件名),二者都可以用--limit-rate 100m选项设置下载速度限制.
curl -i url或-head可以答应http头部信息,无需下载页面就可以查看文件长度等信息。  
curl -d/--data "param1=x&param2=y"
url -o file用于以POST方式发送请求.
wget -post-data url
-O file 以POST方式发送请求.



管道连接的是不同的进程,通常都是脚本的子进程。管道是进程间通讯的一个典型办法, 将一个进程的stdout放到另一个进程的stdin中. 标准的方法是将一个一般命令的输出, 比如cat或者echo, 传递到一个 "过滤命令"(在这个过滤命令中将处理输入)中, 然后得到结果.  作为子进程的运行的管道, 不能够改变脚本的变量.  管道会产生子shell


Bash执行命令的优先级:
别名  关键字  函数  内建命令  脚本或可执行程序($PATH)

对于命令"COMMAND", command COMMAND会直接禁用别名和函数的查找. 这是shell用来影响脚本命令处理效果的三个命令之一. 另外两个分别是builtin和enable

 builtin当你使用builtin BUILTIN_COMMAND的时候, 只会调用shell内建命令"BUILTIN_COMMAND", 而暂时禁用同名的函数, 或者是同名的扩展命令.

enable这个命令或者禁用内建命令或者恢复内建命令. 比如, enable -n kill将禁用内建命令kill, 所以当我们调用kill命令时, 使用的将是/bin/kill外部命令.-a选项会enable所有作为参数的shell内建命令, 不管它们之前是否被enable了


内部命令与内建命令
I/O
echo
: 通常情况下, 每个echo命令都会在终端上新起一行, 但是-n参数会阻止新起一行.
echo命令可以作为输入, 通过管道传递到一系列命令中去
 if echo "$VAR" | grep -q txt # if [[ $VAR = *txt* ]]

 then
 echo "$VAR contains the substring sequence "txt""
 fi

echo命令可以与命令替换组合起来, 这样可以用来设置一个变量.
a=`echo "HELLO" | tr A-Z a-z`
小心echo `command`将会删除任何由command所产生的换行符.

printf
printf命令, 格式化输出, 是echo命令的增强版. 它是C语言printf()库函数的一个有限的变形,并且在语法上有些不同.
printf format-string... parameter...
Pi12=$(printf "%1.12f" $PI)
使用printf的最主要的应用就是格式化错误消息.
printf "$@" >&2 # 格式化传递进来的位置参数, 并把它们送到stderr.
read
从stdin中"读取"一个变量的值, 也就是, 和键盘进行交互, 来取得变量的值. 使用-a参数可以read数组变量。
一个不带变量参数的read命令, 将会把来自键盘的输入存入到专用变量$REPLY中.
一般的, 当输入给read时, 输入一个\, 然后回车, 将会阻止产生一个新行. -r选项将会让 转义.
read命令的-t选项允许时间输入
read命令也可以从重定向的文件中"读取"变量的值. 如果文件中的内容超过一行, 那么只有第一行被分配到这个变量中. 如果read命令的参数个数超过一个, 那么每个变量都会从文件中取得一个分配的字符串作为变量的值, 这些字符串都是以定义的空白字符来进行分隔的. 小心使用! 最后一个变量将会取得第一行剩余的全部部分,如果需要赋值的变量个数比文件中第一行以空白分割的字符串个数还多的话,那么这些变量将会被赋空值.

echo "List of all users:"
OIFS=$IFS; IFS=: # /etc/passwd 使用 ":" 作为域分隔符.
while read name passwd uid gid fullname ignore
do
echo "$name ($fullname)"
done </etc/passwd # I/O 重定向.
IFS=$OIFS # 恢复原始的$IFS.

管道输出到read命令中, 使用管道echo输出来设置变量将会失败.然而, 使用管道cat输出看起来能够正常运行.

 cat file1 file2 |
while read line
do
  echo $line
done

find $1 ( -name "*$2" -o -name ".*$2" ) -print |
while read f; do

文件系统

(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)

cd - 将会把工作目录修改至$OLDPWD, 也就是之前的工作目录.

pwd 打印出当前的工作目录 , 使用这个命令的结果和从内建变量$PWD中所读取的值是相同的.

pushd, popd, dirs  这几个命令可以使得工作目录书签化, 就是可以按顺序向前或向后移动工作目录. 压栈的动作可以保存工作目录列表. 选项可以允许对目录栈做不同的操作.

pushd dir-name把路径dir-name压入目录栈, 同时修改当前目录到dir-name.

popd将目录栈最上边的目录弹出, 同时将当前目录修改为栈顶目录.

dirs列出所有目录栈的内容 (与$DIRSTACK变量相比较). 一个成功的pushd或者popd将会自动调用dirs命令.

变量

let: let命令将执行变量的算术操作. 在许多情况下, 它被看作是复杂的expr命令的一个简化版本.

let a=a+5 等价于 let "a = a + 5"  ;  let "a -= 5" # 等价于 let "a = a - 5"  #双引号和空格更具可读性

eval: eval arg1 [arg2] ... [argN]。将表达式中的参数, 或者表达式列表, 组合起来, 然后评价它们(译者注: 通常用来执行).任何被包含在表达示中的变量都将被扩展(即使被单引号包含).

y=`eval ls -l` # 与 y=`ls -l` 很相似。

echo $y # 换行符将会被删除, 因为"echo"的变量未被""引用.  echo "$y" # 用""将变量引用起来, 换行符就不会被空格替换了.

killppp="eval kill -9 `ps ax | awk '/ppp/ { print $1 }'`" ; $killppp # 这个变量现在成为了一个命令.如果用echo $killppp则只会输出变量内容,不会执行内容。

引号中的命令替换会在赋值时就执行。直接使用$var会将var的内容当做命令执行。y="eval ls"  与 y="ls" 直接在命令行输入$y,前者输出有颜色,后者没有。

总结:要让var的内容作为命令执行,可以在命令行或者脚本中$var,也可以用命令替换result=`$var`或$($var),感觉eval没什么用,最好别用,命令替换已经够用。

eval varname='$(echo "$varvalue" | tr a-z n-za-m)' #如果不用eval单引号内的命令替换不会执行。

eval命令是有风险的, 如果你有更合适的方法来实现功能的话, 尽量避免使用它. eval $COMMANDS将会执行命令COMMANDS的内容, 如果命令中包含有rm-rf *这样的东西, 可能就不是你想要的了. 当你运行一个包含有eval命令的陌生人所编写的代码片段的时候, 这是一件很危险的事情.

set: set命令用来修改内部脚本变量的值. 它的一个作用就是触发选项标志位来帮助决定脚本的行为.另一个作用是以一个命令的结果(set `command`)来重新设置脚本的位置参数. 脚本将会从命令的输出中重新分析出位置参数.

不使用任何选项或参数来调用set命令的话, 将会列出所有的环境变量和其他所有的已经初始化过的变量.

如果使用参数--来调用set命令的话, 将会明确的分配位置参数. 如果--选项后边没有跟变量名的话, 那么结果就使得所有位置参数都被unsets了.

variable="one two three four five" ;  set -- $variable6 # 将位置参数的内容设为变量"$variable"的内容. 

first_param=$1 ;  second_param=$2 ; shift; shift # 将最前面的两个位置参数移除.

set --   # 如果没指定变量,那么将会unset所有的位置参数.

unset: unset命令用来删除一个shell变量, 这个命令的效果就是把这个变量设为null. 但是unset会完整删除变量。注意: 这个命令对位置参数无效.

unset PATH; echo $PATH

unset variable # Unset.  # 与 variable= 效果相同. 但是unset会完整删除变量,使用${var?error_msg}的时候会有区别。

export:  export命令将会使得被export的变量在所运行脚本(或shell)的所有子进程中都可用. 不幸的是,没有办法将变量export到父进程中, 这里所指的父进程就是调用这个脚本的脚本或shell. 关于export命令的一个重要的用法就是使用在启动文件中, 启动文件用来初始化和设置环境变量,这样, 用户进程才能够访问环境变量.

可以在一个操作中同时进行赋值和export变量, 比如: export var1=xxx.

declare, typeset: declare和typeset命令被用来指定或限制变量的属性.

readonly: 与declare -r作用相同, 设置变量的只读属性, 或者可以认为这个变量就是一个常量. 设置了这种属性之后, 如果你还要修改它, 那么将会得到一个错误信息. 这种情况与C语言中的const常量类型是相同的.

脚本行为

source, . (点 命令) : 当在命令行中调用的时候, 这个命令将会执行一个脚本. 当在脚本中调用的时候, source filename将会加载file-name文件. sourc一个文件(或点命令)将会在脚本中引入代码, 并将这些代码附加到脚本中(与C语言中的#include指令效果相同). 最终的结果就像是在使用"source"的行上插入了相应文件的内容. 在多个脚本需要引用相同的数据, 或者需要使用函数库的情况下, 这个命令非常有用.

. data-file # 加载一个数据文件. # 与"source data-file"效果相同, 但是更具可移植性.

被脚本加载的数据文件可以包含变量, 函数, 等等. 在脚本中可以通过'source'或者'.'命令来加载.如果source进来的文件本身就一个可执行脚本的话, 那么它将运行起来, 然后将控制权交还给调用它的脚本. 一个source进来的可执行脚本可以使用return命令来达到这个目的.

也可以向source文件中传递参数, 这些参数将被看作位置参数. source $filename $arg1 arg2 .当然, 脚本会把每个新'source'进来文件的"#!"行都解释成注释, 而不会把它看成是一个新的脚本.

exit :  无条件的停止一个脚本的运行. exit命令可以随意的取得一个整数参数, 然后把这个参数作为这个脚本的退出状态码. 在退出一个简单脚本的时候, 使用exit 0的话, 是种好习惯, 因为这表明成功运行.  如果不带参数调用exit命令退出的话, 那么退出状态码将会将会是脚本中最后一个命令的退出状态码. 等价于exit $?.

exec:  这个shell内建命令将使用一个特定的命令来取代当前进程. 一般的当shell遇到一个命令, 它会forks off一个子进程来真正的运行命令. 使用exec内建命令, shell就不会fork了, 并且命令的执行将会替换掉当前shell. 因此, 在脚本中使用时, 一旦exec所执行的命令执行完毕, 那么它就会强制退出脚本.

exec命令还能够用来重新分配文件描述符. 比如, exec <zzz-file将会用zzz-file来代替stdin.

find命令的-exec选项与shell内建的exec命令是不同的.

caller: 将caller命令放到函数中, 将会在stdout上打印出函数的调用者信息. caller命令也可以在一个被source的脚本中返回调用者信息. 当然这个调用者就是source这个脚本的脚本. 就像函数一样, 这是一个"子例程调用".你会发现这个命令在调试的时候特别有用.

命令

true: 这是一个返回(零)成功退出状态码的命令, 但是除此之外不做任何事.

while true # 这里的true可以用":"来替换

false: 这是一个返回失败退出状态码的命令, 但是除此之外不做任何事.  

if false; then

type [cmd]:  与外部命令which很相像, type cmd将会给出"cmd"的完整路径. 与which命令不同的是, type命令是Bash内建命令. -a是type命令的一个非常有用的选项, 它用来鉴别参数是关键字还是内建命令,也可以用来定位同名的系统命令.

hash [cmds]: 在shell的hash表中, 记录指定命令的路径名, 所以在shell或脚本中调用这个命令的话, 就不需要再在$PATH中重新搜索这个命令了. 如果不带参数的调用hash命令, 它将列出所有已经被hash的命令. -r选项会重新设置hash表. 

bind: bind内建命令用来显示或修改readline  的键绑定.

help: 获得shell内建命令的一个小的使用总结. 与whatis命令比较象, 但help命令是内建命令.

 作业控制命令

jobs: 在后台列出所有正在运行的作业, 给出作业号. 并不象ps命令那么有用.作业和进程的概念太容易混淆了. 特定的内建命令, 比如kill, disown,和wait命令即可以接受作业号为参数, 也可以接受进程号为参数. 但是fg,bg和jobs命令就只能接受作业号为参数.

fg, bg : fg命令可以把一个在后台运行的作业放到前台来运行. 而bg命令将会重新启动一个挂起的作业,并且在后台运行它. 如果使用fg或者bg命令的时候没有指定作业号, 那么默认将对当前正在运行的作业进行操作.

wait : 停止脚本的运行, 直到后台运行的所有作业都结束为止, 或者如果传递了作业号或进程号为参数的话, 那么就直到指定作业结束为止. 返回等待命令的退出状态码.你可以使用wait命令来防止在后台作业没完成(这会产生一个孤儿进程)之前退出脚本.

在一个脚本中, 使用后台运行命令(&)可能会使这个脚本挂起, 直到敲ENTER, 挂起的脚本才会被恢复. 看起来只有在这个命令的结果需要输出到stdout的时候, 这种现象才会出现. 这是个很烦人的现象.  看起来只要在后台运行命令的后边加上一个wait命令就会解决这个问题.   如果将后台运行命令的输出重定向到文件中或/dev/null中, 也能解决这个问题.

suspend : 这个命令的效果与Control-Z很相像, 但是它挂起的是这个shell(这个shell的父进程应该在合适的时候重新恢复它).

logout : 退出一个已经登陆上的shell, 也可以指定一个退出状态码.

kill : 来强制结束一个进程

kill $$ # 脚本将在此处结束自己的进程,"$$"就是脚本的PID.

kill -l将会列出所有信号. kill -9是"必杀"命令. 

这个命令将会结束顽固的不想被kill掉的进程. 有时候kill -15也能干这个活. 一个"僵尸进程",(僵尸进程就是子进程已经结束了, 但是父进程还没kill掉这个子进程), 不能被登陆的用户kill掉 -- 因为你不能杀掉一些已经死了的东西 -- 但是init进程迟早会把它清除干净.

killall : killall命令将会通过名字来杀掉一个正在运行的进程, 而不是通过进程ID. 如果某个特定的命令有多个实例正在运行, 那么执行一次killall命令就会把这些实例全部杀掉.

command : 对于命令"CMD", command CMD会直接禁用别名和函数的查找.  这是shell用来影响脚本命令处理效果的三个命令之一. 另外两个分别是builtin和enable. (注: 当你想运行的命令或函数与内建命令同名时, 由于内建命令比外部命令的优先级高, 而函数比内建命令的优先级高,所以Bash将总会执行优先级比较高的命令. 这样当你想执行优先级低的命令的时候, 就没有选择的余地了. 这三个命令就是用来为你提供这样的机会.)

Bash执行命令的优先级 : 1 别名 2 关键字 3 函数 4 内建命令 5 脚本或可执行程序($PATH)

builtin : 当你使用builtin BUILTIN_COMMAND的时候, 只会调用shell内建命令"BUILTIN_COMMAND", 而暂时禁用同名的函数, 或者是同名的扩展命令.

enable : 这个命令或者禁用内建命令或者恢复内建命令. 比如, enable -n kill将禁用内建命令kill, 所以当我们调用kill命令时, 使用的将是/bin/kill外部命令. -a选项会enable所有作为参数的shell内建命令, 不管它们之前是否被enable了. (译者注: 如果不带参数的调用enable -a, 那么会恢复所有内建命令.) -f filename选项将会从适当的编译过的目标文件 [1] 中, 让enable命令以共享库的形式来加载内建命令. 

 find:  -exec COMMAND; 在每一个find匹配到的文件执行COMMAND命令. 命令序列以;结束(";"是转义符以保证shll传递到find命令中的字符不会被解释为其他的特殊字符).

 如果COMMAND中包含{}, 那么find命令将会用所有匹配文件的路径名来替换"{}".  

 find ~/ -name 'core*' -exec rm {} ; # 从用户的home 目录中删除所有的core dump文件.

expr : 通用求值表达式: 通过给定的操作(参数必须以空格分开)连接参数, 并对参数求值. 可以使算术操作, 比较操作, 字符串操作或者是逻辑操作.在算术表达式expr中使用乘法操作时, 乘法符号必须被转义:expr 5 * 3.     y=`expr $y + 1`与let y=y+1和y=$(($y+1))的效果相同.

z=`expr substr $string $position $length`在位置$position上提取$length长度的子串. :操作可以替换match命令. 比如, b=`expr $a : [0-9]*`与所使用的b=`expr match $a [0-9]*`完全等价.

cut一个从文件中提取特定域的工具. 这个命令与awk中使用的print $N命令很相似, 但是更受限. 在脚本中使用cut命令会比使用awk命令来得容易一些. 最重要的选项就是-d(字段定界符)和-f(域分隔符)选项. uname -a | cut -d" " -f1,3,11,12.    cut -d ' ' -f2,3 filename等价于awk -F'[ ]' '{ print $2, $3 }' filename.

paste :  将多个文件, 以每个文件一列的形式合并到一个文件中, 合并后文件中的每一列就是原来的一个文件.与cut结合使用, 经常用于创建系统log文件.

join : 这个命令与paste命令属于同类命令.  合并两个文件, 这种特殊的形式本质上就是一个关联数据库的简单版本.join命令只能够操作两个文件. 它可以将那些具有特定标记域(通常是一个数字标签)的行合并起来, 并且将结果输出到stdout. 被加入的文件应该事先根据标记域进行排序以便于能够正确的匹配.

grep :使用正则表达式的一个多用途文本搜索工具. 这个命令本来是ed行编辑器中的一个命令/过滤器:g/re/p-- global - regular expression - print.
grep pattern[file...]  在文件中搜索所有pattern出现的位置, pattern既可以是要搜索的字符串, 也可以是一个正则表达式. 当有多个文件参数的时候, grep将会指出哪个文件中包含具体的匹配.  如果在grep命令只搜索一个文件的时候, 那么可以简单的把/dev/null作为第二个文件参数传递给grep: grep Linux osinfo.txt /dev/null    osinfo.txt:This is a

-i选项在搜索时忽略大小写.
-w选项用来匹配整个单词.
-l选项仅列出符合匹配的文件, 而不列出匹配行.
-r(递归) 选项不仅在当前工作目录下搜索匹配, 而且搜索子目录.
-n选项列出所有匹配行, 并显示行号.-v(或者--invert-match)选项将会显示所有不匹配的行.-c(--count) 选项将只会显示匹配到的行数的总数,而不会列出具体的匹配.

如果存在一个成功的匹配, 那么grep命令将会返回0作为退出状态码, 这样就可以将grep命令的结果放在脚本的条件测试中来使用, 尤其和-q(禁止输出)选项组合时特别有用.

grep -q "$word" "$filename" # "-q"选项将使得什么都不输出到stdout上.
 if [ $? -eq $SUCCESS ]

在脚本中模拟"grep"的行为:

for file in * # 遍历$PWD下的所有文件.
do
   output=$(sed -n /"$1"/p $file)   # 命令替换.
   if [ ! -z "$output" ]   # 如果"$output"不加双引号将会发生什么?
  then
     echo -n "$file: "
     echo $output
   fi           # sed -ne "/$1/s|^|${file}: |p" 这句与上边这段等价.
   echo
 done
egrep- 扩展的grep- 这个命令与grep -E等价  fgrep- 快速的grep- 这个命令与grep -F等价

sed, awk
这个两个命令都是独立的脚本语言, 尤其适合分析文本文件和命令输出. 既可以单独使用, 也可以结合管道和在shell脚本中使用.

wc

wc -w统计单词数量.
wc -l统计行数量.
wc -c统计字节数量.
wc -m统计字符数量.
wc -L给出文件中最长行的长度.

tr : 字符转换过滤器.   必须使用引用或中括号, 这样做才是合理的. 引用可以阻止shell重新解释出现在tr命令序列中的特殊字符. 中括号应该被引用起来防止被shell扩展.

-d选项删除指定范围的字符.     -s选项用来在重复字符序列中除去除第一个字符以外的所有字符. 这个选项在删除多余空白的时候非常有用.

-c"complement"选项将会反转匹配的字符集. 通过这个选项, tr将只会对那些不匹配的字符起作用.

for filename in * # 遍历当前目录下的所有文件. 转换为小写文件名
do
   fname=`basename $filename`
  n=`echo $fname | tr A-Z a-z` # 将名字修改为小写.
  if [ "$fname" != "$n" ] # 只对那些文件名不是小写的文件进行重命名.
  then
    mv $fname $n
  fi
done

# 对于那些文件名中包含空白和新行的文件, 上边的脚本就不能工作了,因此建议使用下边的方法

for filename in * # 不必非得使用basename命令,  因为"*"不会返回任何包含"/"的文件.
do

  n=`echo "$filename/" | tr '[:upper:]' '[:lower:]'`   # POSIX 字符集标记法. 添加的斜线是为了在文件名结尾换行不会被 命令替换删掉.
  n=${n%/} # 变量替换:从文件名中将上边添加在结尾的斜线删除掉.
  [[ $filename == $n ]] || mv "$filename" "$n"   # 检查文件名是否已经是小写.
done
exit $?

fold: 将输入按照指定宽度进行折行. 这里有一个非常有用的选项-s, 这个选项可以使用空格进行断行

fmt : 一个简单的文件格式器, 通常用在管道中, 将一个比较长的文本行输出进行"折行".

  WIDTH=40 # 设为40列宽.
  b=`ls /usr/local/bin` # 取得文件列表...
  echo $b | fmt -w $WIDTH
  # 也可以使用如下方法, 作用是相同的.
  # echo $b | fold - -s -w $WIDTH

column: 列格式化工具. 通过在合适的位置插入tab, 这个过滤工具会将列类型的文本转化为"易于打印"的表格式进行输出.

colrm: 列删除过滤器. 这个工具将会从文件中删除指定的列(列中的字符串)并且写到文件中, 如果指定的列不存在, 那么就回到stdout. colrm 2 4 <filename将会删除filename文件中每行的第2到第4列之间的所有字符.如果这个文件包含tab和不可打印字符, 那将会引起不可预期的行为. 在这种情况下, 应该通过管道的手段使用expand和unexpand来预处理colrm.

nl:计算行号过滤器. nl filename将会把filename文件的所有内容都输出到stdout上, 但是会在每个非空行的前面加上连续的行号. 如果没有filename参数, 那么就操作stdin.nl命令的输出与cat -n非常相似, 区别就是'cat -n'对空行也进行计数 注意'nl -ba'也会这么做.然而默认情况下nl不会列出空行,cat -b也不会。

通讯命令

host: 通过名字或IP地址来搜索一个互联网主机的信息, 使用DNS.

ipcalc: 显示一个主机IP信息. 使用-h选项, ipcalc将会做一个DNS的反向查询, 通过IP地址找到主机(服务器)名.

nslookup: 通过IP地址在一个主机上做一个互联网的"名字服务查询". 事实上, 这与ipcalc -h或dig -x等价. 这个命令既可以交互运行也可以非交互运行, 换句话说, 就是在脚本中运行.

dig: Domain Information Groper(域信息查询). 与nslookup很相似, dig也可以在一个主机上做互联网的"名字服务查询".

traceroute: 跟踪包发送到远端主机过程中的路由信息. 这个命令在LAN, WAN, 或者在Internet上都可以正常工作. 远端主机可以通过IP地址来指定. 这个命令的输出也可以通过管道中的grep或sed命令来过滤.

ping: 广播一个"ICMP ECHO_REQUEST"包到其他主机上, 既可以是本地网络也可以是远端网络. 这是一个测试网络连接的诊断工具, 应该小心使用.如果ping成功之行, 那么返回的退出状态码为0. 可以用在脚本的测试语句中。

whois: 执行DNS(域名系统)查询. -h选项允许指定需要查询的特定whois服务器. 

finger: 取得网络上的用户信息. 另外这个命令可以显示一个用户的~/.plan, ~/.project,和~/.forward文件, 当然, 前提是如果这些文件存在的话.

vrfy: 验证一个互联网的e-mail地址.

ftp: 向远端服务器上传或下载的工具, 也是一种协议. 一个ftp会话可以写到脚本中自动运行.

telnet: 连接远端主机的工具和协议.telnet协议本身包含安全漏洞, 因此我们应该适当的避免使用

wget: wget工具使用非交互的形式从web或ftp站点上取得或下载文件. 在脚本中使用正好.

   wget -p http://www.xyz23.com/file01.html    # -p或--page-requisite选项将会使得wget取得所有在显示指定页时所需要的文件. (译者: 比如内嵌图片和样式表等.)
   wget -r ftp://ftp.xyz24.net/~bozo/project_files/ -O $SAVEFILE  # -r选项将会递归的从指定站点上下载所有连接.

rcp: 远端拷贝, 在网络上的不同主机间拷贝文件.

rsync: 远端同步, 在网络上的不同主机间(同步)更新文件.

在使用rcp, rsync, 还有另外一些有安全问题的类似工具的时候, 你应该考虑使用ssh, scp, 或者expect脚本来代替这些不安全的工具。

ssh: 安全shell, 登陆远端主机并在其上运行命令. 这个工具具有身份认证和加密的功能, 可以安全的替换telnet, rlogin, rcp, 和rsh等工具. 请参考这个工具的man页来获取详细信息.

scp: 安全拷贝, 在功能上与rcp很相似, 就是在两个不同的网络主机之间拷贝文件, 但是要使用鉴权的方式, 并且要使用与ssh类似的安全层.

netconfig:用来配置网络适配器(使用DHCP)的命令行工具. 这个命令对于红帽发行版来说是内置的.

bc: Bash不能处理浮点运算, 并且缺乏特定的一些操作, 这些操作都是一些重要的计算功能. 幸运的是, bc可以解决这个问题。这里有一个简单的使用bc命令的模版, 可以用来计算脚本中的变量. 这个模版经常用于命令替换中.    variable=$(echo "OPTIONS; OPERATIONS" | bc)。

调用bc的另一种方法就是here document, 并把它嵌入到命令替换块中。

variable=`bc << LIMIT_STRING
options
statements
operations
 LIMIT_STRING
 `

var1=`bc << EOF   # 使用$( ... )这种标记法也可以.
18.33 * 19.78
 EOF
`    echo $var1 # 362.56

混杂命令

jot, seq: 这些工具用来生成一系列整数, 用户可以指定生成范围.每个产生出来的整数一般都占一行, 但是可以使用-s选项来改变这种设置.   seq -s : 5  #1:2:3:4:5

 for a in `seq $BEGIN $INTERVAL $END`

tee: 这是一个重定向操作, 但是与之前所看到的有点不同. 就像管道中的"三通"一样, 这个命令可以将命令或者管道命令的输出"抽出"到一个文件中, 而且不影响结果.

   cat listfile* | sort | tee check.file | uniq > result.file(在对排序的结果进行uniq(去掉重复行)之前, 文件check.file保存了排过序的"listfiles". )

命令替换

命令替换的典型用法形式, 是使用后置引用(`...`). 使用后置引用的(反引号)命令会产生命令行文本.$(ls *.txt) # 这是命令替换的另一种形式.对于命令替换来说, $(COMMAND)形式已经取代了后置引用"`"

命令替换将会调用一个subshell,命令替换可能会引起单词分割(word split).

COMMAND `echo a b` # 两个参数: a and b  COMMAND "`echo a b`" # 1个参数: "a b"  COMMAND `echo` # 无参数  COMMAND "`echo`" # 一个空参数

即使没有引起单词分割(word split), 命令替换也会去掉多余的新行.

如果用echo命令输出一个未引用变量, 而且这个变量以命令替换的结果作为值, 那么这个变量中的换行符将会被删除. 这可能会引起一些异常状况.

命令替换甚至允许将整个文件的内容放到变量中, 可以使用重定向或者cat命令.variable1=`<file1`   variable2=`cat file2` #  将"file1"的内容放到"variable1"中.

$(...)形式的命令替换在处理双反斜线(\)时与`...`形式不同. echo `echo \` #无输出  echo $(echo \)  #

$(...)形式的命令替换是允许嵌套的,word_count=$( wc -w $(ls -l | awk '{print $9}') )

 对于命令替换来说, 这个命令既可以是外部的系统命令, 也可以是内部脚本的内建命令,甚至可以是脚本函数.

从技术的角度来讲, 命令替换将会抽取一个命令的输出, 然后使用=操作将其赋值到一个变量中。

算术扩展

 使用后置引用的算术扩展(通常都是和expr一起使用):z=`expr $z + 3`。

使用双括号形式的算术扩展, 也可以使用let命令:后置引用形式的算术扩展已经被双括号形式所替代了 -- ((...))和$((...))

z=$(($z+3))或 z=$((z+3)),(( n += 1 )),let z=z+3, let "z += 3" # 使用引用的形式, 允许在变量赋值的时候存在空格.

原文地址:https://www.cnblogs.com/fly-xiang-zhao/p/3708944.html