讲解一
1.概念
位置参数(position parameter)
运行脚本前(调用函数前),shell 传递给脚本的参数。
2. 原理
bash 脚本的位置参数的传递可以做如下理解:
1. shell将用户输入的命令行 分别赋值给 1, 2, 3, 4, 5....N
2. 然后将最后一个参数的名称 N 赋值给 #
例如: ./script.sh pa1 pa2 pa3 pa4 pa5
1="pa1"; 2="pa2"; 3="pa3" ; 4="pa4"; 5="pa5" && #=5 # 一个间接引用
3. 应用:
echo "$1" # 打印 pa1
echo "$2" # 打印 pa2
echo "$#" # 打印的是最后一个参数的序号, 即位置参数的个数 5
echo "$(eval echo "/$$#")" # 打印的是最后一个参数的值
echo "${!#}" # 打印的是最后一个参数的值
echo "$@" # 打印所有位置参数,IFS为间隔符号
echo "$*" # 打印所有位置参数,无间隔符号
函数参数传递:函数的值传递,全部都是 字符串的传递,而且是值传递。
例如:将一个数组名作为参数传递给一个函数时,函数里面使用该参数时,则认为其只是一个字符串。
e.g:
#!/bin/bash
declare -a arr
func(){
#$1[0]="first element of array" # error! command not found
arr[0]="first element of array" # right
}
func arr
tips: 将一个文本文件的内容赋值给一个变量
这个比较牛: str=$(<file) #<file == 0<file
我写的:read str < <(echo file| tr "/n" " ")
讲解二
linux中shell变量$#,$@,$0,$1,$2的含义解释:
变量说明:
$$
Shell本身的PID(ProcessID)
$!
Shell最后运行的后台Process的PID
$?
最后运行的命令的结束代码(返回值)
$-
使用Set命令设定的Flag一览
$*
所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$@
所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$#
添加到Shell的参数个数
$0
Shell本身的文件名
$1~$n
添加到Shell的各参数值。$1是第1参数、$2是第2参数…。
我们先写一个简单的脚本,执行以后再解释各个变量的意义
# touch variable
# vi variable
脚本内容如下:
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@"
保存退出
赋予脚本执行权限
# chmod +x variable
执行脚本
# ./variable aa bb
number:2
scname:./variable
first: aa
second:bb
argume:aa bb
通过显示结果可以看到:
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1是传递给该shell脚本的第一个参数
$2是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
魔术数字
编辑 锁定
理由编辑
-
参考资料
Linux命令替换
Linux命令替换和重定向有些相似,但区别在于命令替换是将一个命令的输出作为另外一个Linux命令的参数。常用命令格式为: command1 `command2` 其中,command2的输出将作为command1的参数。需要注意的是这里的`符号,被它括起来的内容将作为Linux命令执行,执行后的结果作为command1的参数。例如: $ cd `pwd`
该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
登录shell和非登录shell
(2012-09-25 14:00:03)事实上还有很多特殊符号可用来分隔单个的命令:分号(;)、管道(|)、&、逻辑AND (&&),还有逻辑OR (||)。对于每一个读取的管道,Shell都回将命令分割,为管道设置I/O,并且对每一个命令依次执行下面的操作:

整个步骤顺序如上图所示,看起来有些复杂。当命令行被处理时,每一个步骤都是在Shell的内存里发生的;Shell不会真的把每个步骤的发生显示给你看。所以,你可以假想这事我们偷窥Shell内存里的情况,从而知道每个阶段的命令行是如何被转换的。我们从这个例子开始说:
$ mkidr /tmp/x 建立临时性目录
$ cd /tmp/x 切换到该目录
$ touch f1 f2 建立文件
$ f=f y="a b" 赋值两个变量
$ echo ~+/${f}[12] $y $(echo cmd subst )$ (( 3 + 2 )) > out 将结果重定向到out
上述的执行步骤概要如下:
1.命令一开始回根据Shell语法而分割为token。最重要的一点是:I/O重定向 >out 在这里是被识别的,并存储供稍后使用。流程继续处理下面这行,其中每个token的范围显示于命令下面的行上:
echo ~+/${f}[12] $y $(echo cmd subst) $((3 + 2))
| 1 | |----- 2 ----| |3 | |-------- 4----------| |----5-----|
2.检查第一个单词(echo)是否为关键字,例如 if 或 for 。这里不是,所以命令行不变继续处理。
3.检查第一个单词(echo)是否为别名。这里不是。所以命令行不变,继续处理。
4.扫描所以单词是否需要波浪号展开。在本例中,~+ 为ksh93 与 bash 的扩展,等同于$PWD,也就是当前的目录。token 2将被修改,处理如下:
echo /tmp/x/${f}[12] $y $(echo cmd subst) $((3 + 2))
| 1 | |------- 2 -------| |3 | |-------- 4----------| |----5-----|
5.下一步是变量展开:token 2 与 3 都被修改。这样会产生:
echo /tmp/x/${f}[12] a b $(echo cmd subst) $((3 + 2))
| 1 | |------- 2 -------| | 3 | |-------- 4----------| |----5-----|
6.再来要处理的是命令替换。注意,这里可用递归应用列表里的所有步骤!在这里,命令替换修改了 token 4:
echo /tmp/x/${f}[12] a b cmd subst $((3 + 2))
| 1 | |------- 2 -------| | 3 | |--- 4 ----| |----5-----|
7.现在执行算数替换。修改的是 token 5,结果:
echo /tmp/x/${f}[12] a b cmd subst 5
| 1 | |------- 2 -------| | 3 | |--- 4 ----| |5|
8.前面所有的展开产生的结果,都将再一次被扫描,看看是否有 $IFS 字符。如果有,则他们是作为分隔符(separator),产生额外的单词,例如,两个字符$y 原来是组成一个单词,单展开式“a- 空格-b”,在此阶段被切分为两个单词:a 与 b。相同方式也应用于命令$(echo cmd subst)的结果上。先前的 token 3 变成了 token 3 与
token 4.先前的 token 4则成了 token 5 与 token 6。结果:
echo /tmp/x/${f}[12] a b cmd subst 5
| 1 | |------- 2 -------| 3 4 |-5-| |- 6 -| 7
9.最后的替换阶段是通配符展开。token 2 变成了 token 2 与 token 3:
echo /tmp/x/$f1 /tmp/x/$f2 a b cmd subst 5
| 1 | |---- 2 ----| |---- 3 ----| 4 5 |-6-| |- 7 -| 8
10.这时,Shell已经准备好了要执行最后的命令了。它会去寻找 echo。正好 ksh93 与 bash 的 echo 都内建到Shell 中了。
11.Shell实际执行命令。首先执行 > out 的 I/O重定向,再调用内部的 echo 版本,显示最后的参数。
最后的结果:
$cat out
/tmp/x/f1 /tmp/x/f2 a b cmd subst 5

We've seen how the shell uses
We've touched upon command-line processing (see
[7] Even this explanation is slightly simplified to elide the most petty details, e.g., "middles" and "ends" of compound commands, special characters within
[[ ... ]] and (( ... )) constructs, etc. The last word on this subject is the reference book, The KornShell Command and Programming Language , by Morris Bolsky and David Korn, published by Prentice-Hall.
-
Splits the command into
tokens that are separated by the fixed set of metacharacters : SPACE, TAB , NEWLINE, ;
, ( ,
), < , > , | , and & . Types of tokens include words , keywords , I/O redirectors, and semicolons. -
Checks the first token of each command to see if it is a
keyword with no quotes or backslashes. If it's an opening keyword ( if and other control-structure openers, function , { , ( , (( , or [[ ), then the command is actually acompound command . The shell sets things up internally for the compound command, reads the next command, and starts the process again. If the keyword isn't a compound command opener (e.g., is a control-structure "middle" like then ,else , or do , an "end" like fi or done , or a logical operator), the shell signals a syntax error. -
Checks the first word of each command against the list of
aliases . If a match is found, it substitutes the alias' definition and goes back to Step 1 ; otherwise it goes on to Step 4. This scheme allows recursive aliases; seeChapter 3 . It also allows aliases for keywords to be defined, e.g., alias aslongas=while or alias procedure=function . -
Substitutes the user's home directory (
$HOME ) for tilde if it is at the beginning of a word. Substitutes user 's home directory for ~
user . [8] [8]
Two obscure variations on this: the shell substitutes the current directory ( $PWD ) for ~+ and the previous directory ( $OLDPWD ) for ~- . -
Performs
parameter (variable) substitution for any expression that starts with a dollar sign ( $ ). -
Does
command substitution for any expression of the form $( string ) . -
Evaluates
arithmetic expressions of the form $(( string )) . -
Takes the parts of the line that resulted from parameter, command, and arithmetic substitution and splits them into words again. This time it uses the characters in
$IFS as delimiters instead of the set of metacharacters in Step 1. -
Performs
filename generation , a.k.a. wildcard expansion , for any occurrences of *
, ?
, and [/] pairs. It also processes the regular expression operators that we saw in Chapter 4 . Figure 7.1: Steps in Command-line Processing
-
Uses the first word as a command by looking up its source according to the rest of the list in
Chapter 4 , i.e., as a built-in command, then as a function , then as a file in any of the directories in $PATH . -
Runs the command after setting up I/O redirection and other such things.
That's a lot of steps
alias ll="ls -l"
Further assume that a file exists called
Now let's see how the shell processes the following command:
ll $(whence cc) ~fred/.*$(($$00))
Here is what happens to this line:
-
ll $(whence cc) ~fred/.*$(($$00))
Splitting the input into words.
-
ll
is not a keyword, so step 2 does nothing. -
ls -l $(whence cc) ~fred/.*$(($$00))
Substituting
ls -l for its alias "ll". The shell then repeats steps 1 through 3; step 2 splits the ls -l into two words. [9] [9] Some of the shell's built-in aliases, however, seem to make it through single quotes:
true (an alias for : , a "do-nothing" command that always returns exit status 0), false (an alias for let 0 , which always returns exit status 1), and stop (an alias for kill -STOP ). -
ls -l $(whence cc) /home/fred/.*$(($$00))
Expanding
~fred into /home/fred . -
ls -l $(whence cc) /home/fred/.*$((253700))
Substituting
2537 for $$ . -
ls -l /usr/bin/cc /home/fred/.*$((253700))
Doing command substitution on "whence cc".
-
ls -l /usr/bin/cc /home/fred/.*537
Evaluating the arithmetic expression
253700 . -
ls -l /usr/bin/cc /home/fred/.*537
This step does nothing.
-
ls -l /usr/bin/cc /home/fred/.hist537
Substituting the filename for the wildcard expression .*
537 . -
The command
ls is found in /usr/bin . -
/usr/bin/ls
is run with the option -l and the two arguments.
Although this list of steps is fairly straightforward, it is not the whole story. There are still two ways to
source命令用法:
source FileName
作用:在当前bash环境下读取并执行FileName中的命令。
注:该命令通常用命令“.”来替代。
如:source.bash_rc与. .bash_rc是等效的。
注意:source命令与shell scripts的区别是,
source在当前bash环境下执行命令,而scripts是启动一个子shell来执行命令。这样如果把设置环境变量(或alias等等)的命令写进scripts中,就只会影响子shell,无法改变当前的BASH,所以通过文件(命令列)设置环境变量时,要用source命令。

一直弄不懂,管道不就是把前一个命令的结果作为参数给下一个命令吗,那在 | 后面加不加xargs有什么区别
NewUserFF 写道:
懒蜗牛Gentoo 写道:
管道是实现“将前面的标准输出作为后面的标准输入”
xargs是实现“将标准输入作为命令的参数”
你可以试试运行:
代码:
echo "--help"|cat
echo "--help"|xargs cat
看看结果的不同。
试过了,依然不是很确定的明白到底是什么意思,自己再探索一下看看把
如果你直接在命令行输入cat而不输入其余的任何东西,这时候的cat会等待标准输入,因此你这时候可以
通过键盘输入并按回车来让cat读取输入,cat会原样返回。而如果你输入--help,那么cat程序会在标准输出上
打印自己的帮助文档。也就是说,管道符 | 所传递给程序的不是你简单地在程序名后面输入的参数,它们会被
程序内部的读取功能如scanf和gets等接收,而xargs则是将内容作为普通的参数传递给程序,相当于你手写了
cat --help
来自:http://forum.ubuntu.org.cn/viewtopic.php?t=354669
补充解释:
在一个目录中有如下三个文件
a.c b.c c.c
find . / -print命令会打印出三个文件名
find . / -print | grep a.c 只会打印出a.c这个文件
如果只输入命令grep a.c
那么你在键盘中只输入a.c字符串时,a.c会被打印两次,否则只打印你输入的字符
如果要找三个文件中,那个文件包括有hello字符
find ./ -print | xargs grep hello
总结:管道符后不加xargs相当于先将xargs后面的命令回车执行一下再从键盘里输入
管道符前面命令执行的结果内容
加上xargs 相当于直接从键盘输入管道符前面命令执行的结果内容再回车
再总结一下,就是回车的先后顺序不太一样。
echo是一种最常用的与广泛使用的内置于Linux的bash和C shell的命令,通常用在脚本语言和批处理文件中来在标准输出或者文件中显示一行文本或者字符串。
echo命令的语法是:
- echo [选项] [字符串]
1. 输入一行文本并显示在标准输出上
- $ echo Tecmint is a community of Linux Nerds
会输出下面的文本:
- Tecmint is a community of Linux Nerds
2. 输出一个声明的变量值
比如,声明变量x并给它赋值为10。
- $ x=10
会输出它的值:
- $ echo The value of variable x = $x
- The value of variable x = 10
3. 使用‘\b‘选项
‘-e‘后带上'\b'会删除字符间的所有空格。
注意: Linux中的选项‘-e‘扮演了转义字符反斜线的翻译器。
- $ echo -e "Tecmint \bis \ba \bcommunity \bof \bLinux \bNerds"
- TecmintisacommunityofLinuxNerds
4. 使用‘\n‘选项
‘-e‘后面的带上‘\n’行会在遇到的地方作为新的一行
- $ echo -e "Tecmint \nis \na \ncommunity \nof \nLinux \nNerds"
- Tecmint
- is
- a
- community
- of
- Linux
- Nerds
5. 使用‘\t‘选项
‘-e‘后面跟上‘\t’会在空格间加上水平制表符。
- $ echo -e "Tecmint \tis \ta \tcommunity \tof \tLinux \tNerds"
- Tecmint is a community of Linux Nerds
6. 也可以同时使用换行‘\n‘与水平制表符‘\t‘
- $ echo -e "\n\tTecmint \n\tis \n\ta \n\tcommunity \n\tof \n\tLinux \n\tNerds"
- Tecmint
- is
- a
- community
- of
- Linux
- Nerds
7. 使用‘\v‘选项
‘-e‘后面跟上‘\v’会加上垂直制表符。
- $ echo -e "\vTecmint \vis \va \vcommunity \vof \vLinux \vNerds"
- Tecmint
- is
- a
- community
- of
- Linux
- Nerds
8. 也可以同时使用换行‘\n‘与垂直制表符‘\v‘
- $ echo -e "\n\vTecmint \n\vis \n\va \n\vcommunity \n\vof \n\vLinux \n\vNerds"
- Tecmint
- is
- a
- community
- of
- Linux
- Nerds
注意: 你可以按照你的需求连续使用两个或者多个垂直制表符,水平制表符与换行符。
9. 使用‘\r‘选项
‘-e‘后面跟上‘\r’来指定输出中的回车符。(LCTT 译注:会覆写行开头的字符)
- $ echo -e "Tecmint \ris a community of Linux Nerds" <li class="L1" style="word-wrap:break-word; margin:0px%