Linux中的三剑客之grep
grep简介
Linux中的三剑客: grep sed awk
grep全程: Global search Regular Expression and Print out the line
grep man
GREP(1) BSD General Commands Manual GREP(1)
NAME
grep, egrep, fgrep, zgrep, zegrep, zfgrep -- file pattern searcher
SYNOPSIS
grep [-abcdDEFGHhIiJLlmnOopqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color[=when]] [--colour[=when]]
[--context[=num]] [--label] [--line-buffered] [--null] [pattern] [file ...]
DESCRIPTION
The grep utility searches any given input files, selecting lines that match one or more patterns. By default, a pattern matches an input line if the
regular expression (RE) in the pattern matches the input line without its trailing newline. An empty expression matches every line. Each input line
that matches at least one of the patterns is written to the standard output.
grep is used for simple patterns and basic regular expressions (BREs); egrep can handle extended regular expressions (EREs). See re_format(7) for
more information on regular expressions. fgrep is quicker than both grep and egrep, but can only handle fixed patterns (i.e. it does not interpret
regular expressions). Patterns may consist of one or more lines, allowing any of the pattern lines to match a portion of the input.
zgrep, zegrep, and zfgrep act like grep, egrep, and fgrep, respectively, but accept input files compressed with the compress(1) or gzip(1) compression
utilities.
The following options are available:
-A num, --after-context=num
Print num lines of trailing context after each match. See also the -B and -C options.
-a, --text
Treat all files as ASCII text. Normally grep will simply print ``Binary file ... matches'' if files contain binary characters. Use of this
option forces grep to output lines matching the specified pattern.
-B num, --before-context=num
Print num lines of leading context before each match. See also the -A and -C options.
-b, --byte-offset
The offset in bytes of a matched pattern is displayed in front of the respective matched line.
-C[num, --context=num]
Print num lines of leading and trailing context surrounding each match. The default is 2 and is equivalent to -A 2 -B 2. Note: no whitespace
may be given between the option and its argument.
-c, --count
Only a count of selected lines is written to standard output.
--colour=[when, --color=[when]]
Mark up the matching text with the expression stored in GREP_COLOR environment variable. The possible values of when can be `never', `always'
or `auto'.
-D action, --devices=action
Specify the demanded action for devices, FIFOs and sockets. The default action is `read', which means, that they are read as if they were
normal files. If the action is set to `skip', devices will be silently skipped.
-d action, --directories=action
Specify the demanded action for directories. It is `read' by default, which means that the directories are read in the same manner as normal
files. Other possible values are `skip' to silently ignore the directories, and `recurse' to read them recursively, which has the same effect
as the -R and -r option.
-E, --extended-regexp
Interpret pattern as an extended regular expression (i.e. force grep to behave as egrep).
-e pattern, --regexp=pattern
Specify a pattern used during the search of the input: an input line is selected if it matches any of the specified patterns. This option is
most useful when multiple -e options are used to specify multiple patterns, or when a pattern begins with a dash (`-').
--exclude
If specified, it excludes files matching the given filename pattern from the search. Note that --exclude patterns take priority over
--include patterns, and if no --include pattern is specified, all files are searched that are not excluded. Patterns are matched to the full
path specified, not only to the filename component.
--exclude-dir
If -R is specified, it excludes directories matching the given filename pattern from the search. Note that --exclude-dir patterns take prior-
ity over --include-dir patterns, and if no --include-dir pattern is specified, all directories are searched that are not excluded.
-F, --fixed-strings
Interpret pattern as a set of fixed strings (i.e. force grep to behave as fgrep).
-f file, --file=file
Read one or more newline separated patterns from file. Empty pattern lines match every input line. Newlines are not considered part of a
pattern. If file is empty, nothing is matched.
-G, --basic-regexp
Interpret pattern as a basic regular expression (i.e. force grep to behave as traditional grep).
-H Always print filename headers with output lines.
-h, --no-filename
Never print filename headers (i.e. filenames) with output lines.
--help Print a brief help message.
-I Ignore binary files. This option is equivalent to --binary-file=without-match option.
-i, --ignore-case
Perform case insensitive matching. By default, grep is case sensitive.
--include
If specified, only files matching the given filename pattern are searched. Note that --exclude patterns take priority over --include pat-
terns. Patterns are matched to the full path specified, not only to the filename component.
--include-dir
If -R is specified, only directories matching the given filename pattern are searched. Note that --exclude-dir patterns take priority over
--include-dir patterns.
-J, --bz2decompress
Decompress the bzip2(1) compressed file before looking for the text.
-L, --files-without-match
Only the names of files not containing selected lines are written to standard output. Pathnames are listed once per file searched. If the
standard input is searched, the string ``(standard input)'' is written.
-l, --files-with-matches
Only the names of files containing selected lines are written to standard output. grep will only search a file until a match has been found,
making searches potentially less expensive. Pathnames are listed once per file searched. If the standard input is searched, the string
``(standard input)'' is written.
--mmap Use mmap(2) instead of read(2) to read input, which can result in better performance under some circumstances but can cause undefined behav-
iour.
-m num, --max-count=num
Stop reading the file after num matches.
-n, --line-number
Each output line is preceded by its relative line number in the file, starting at line 1. The line number counter is reset for each file pro-
cessed. This option is ignored if -c, -L, -l, or -q is specified.
--null Prints a zero-byte after the file name.
-O If -R is specified, follow symbolic links only if they were explicitly listed on the command line. The default is not to follow symbolic
links.
-o, --only-matching
Prints only the matching part of the lines.
-p If -R is specified, no symbolic links are followed. This is the default.
-q, --quiet, --silent
Quiet mode: suppress normal output. grep will only search a file until a match has been found, making searches potentially less expensive.
-R, -r, --recursive
Recursively search subdirectories listed.
-S If -R is specified, all symbolic links are followed. The default is not to follow symbolic links.
-s, --no-messages
Silent mode. Nonexistent and unreadable files are ignored (i.e. their error messages are suppressed).
-U, --binary
Search binary files, but do not attempt to print them.
-V, --version
Display version information and exit.
-v, --invert-match
Selected lines are those not matching any of the specified patterns.
-w, --word-regexp
The expression is searched for as a word (as if surrounded by `[[:<:]]' and `[[:>:]]'; see re_format(7)).
-x, --line-regexp
Only input lines selected against an entire fixed string or regular expression are considered to be matching lines.
-y Equivalent to -i. Obsoleted.
-Z, -z, --decompress
Force grep to behave as zgrep.
--binary-files=value
Controls searching and printing of binary files. Options are binary, the default: search binary files but do not print them; without-match:
do not search binary files; and text: treat all files as text.
--context[=num]
Print num lines of leading and trailing context. The default is 2.
--line-buffered
Force output to be line buffered. By default, output is line buffered when standard output is a terminal and block buffered otherwise.
If no file arguments are specified, the standard input is used.
ENVIRONMENT
GREP_OPTIONS May be used to specify default options that will be placed at the beginning of the argument list. Backslash-escaping is not supported,
unlike the behavior in GNU grep.
EXIT STATUS
The grep utility exits with one of the following values:
0 One or more lines were selected.
1 No lines were selected.
>1 An error occurred.
EXAMPLES
To find all occurrences of the word `patricia' in a file:
$ grep 'patricia' myfile
To find all occurrences of the pattern `.Pp' at the beginning of a line:
$ grep '^\.Pp' myfile
The apostrophes ensure the entire expression is evaluated by grep instead of by the user's shell. The caret `^' matches the null string at the begin-
ning of a line, and the `\' escapes the `.', which would otherwise match any character.
To find all lines in a file which do not contain the words `foo' or `bar':
$ grep -v -e 'foo' -e 'bar' myfile
A simple example of an extended regular expression:
$ egrep '19|20|25' calendar
Peruses the file `calendar' looking for either 19, 20, or 25.
SEE ALSO
ed(1), ex(1), gzip(1), sed(1), re_format(7)
STANDARDS
The grep utility is compliant with the IEEE Std 1003.1-2008 (``POSIX.1'') specification.
The flags [-AaBbCDdGHhIJLmoPRSUVwZ] are extensions to that specification, and the behaviour of the -f flag when used with an empty pattern file is
left undefined.
All long options are provided for compatibility with GNU versions of this utility.
Historic versions of the grep utility also supported the flags [-ruy]. This implementation supports those options; however, their use is strongly
discouraged.
HISTORY
The grep command first appeared in Version 6 AT&T UNIX.
BUGS
The grep utility does not normalize Unicode input, so a pattern containing composed characters will not match decomposed input, and vice versa.
BSD July 28, 2010 BSD
Linux中的三剑客之awk命令
awk 去重 重复的数据只保留一条
##去重,重复的数据只保留一条
##1. 内容输出到终端 (以下两个效果一样)
cat test.sql | awk '!a[$0]++{print}'
cat test.sql | awk '!a[$1]++{print}'
##2. 内容输出到文件
awk '!a[$0]++' test.sql >> test-1.sql
awk 去重 只显示重复行
##去重,只显示重复行
##1. 内容输出到终端
cat test.sql| awk 'a[$0]++{print}'
##2. 内容输出到文件
awk 'a[$0]++' test.sql >> test-2.sql
shell基础学习
运行
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell
#!/bin/bash
echo "Hello World !"
运行方法:(上面的代码保存为 test.sh,并 cd 到相应目录)
作为可执行程序
chmod +x ./test.sh #使脚本具有执行权限 ./test.sh #执行脚本
作为解释器参数
/bin/sh test.sh /bin/php test.php
注释
以"#"开头的行就是注释,会被解释器忽略。
sh里没有多行注释,只能每一行加一个#号
多行注释 变通方法
将这些多行定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。
变量
定义变量
your_name="qinjx"
#变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
#建议都加 花括号
echo $your_name
echo ${your_name}
for file in `ls /etc`
#或
for file in $(ls /etc)
只读变量
myUrl="http://www.w3cschool.cc"
readonly myUrl
#下面这句会报错
myUrl="http://www.runoob.com"
删除变量
unset variable_name
#变量被删除后不能再次使用。unset 命令不能删除只读变量。
myUrl="http://www.runoob.com"
unset myUrl
#下面这个echo没任何输出
echo $myUrl
变量类型
- 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号
单引号
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字串中不能出现单引号(对单引号使用转义符后也不行)。
双引号
双引号的优点:
双引号里可以有变量
双引号里可以出现转义字符
拼接字符串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
获取字符串长度
string="abcd"
echo ${#string} #输出 4
提取子字符串
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo ##从字符串第 2 个字符开始截取 4 个字符
查找子字符串
string="runoob is a great company"
echo `expr index "$string" is` # 输出 8
数组
定义数组
在Shell中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
array_name=(value0 value1 value2 value3)
#或
array_name=(
value0
value1
value2
value3
)
#或 单独定义数组的各个分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
读取数组
${数组名[下标]}
valuen=${array_name[n]}
#使用@符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
数组长度
获取数组长度的方法与获取字符串长度的方法相同
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
##################################执行输出
$ chmod +x test.sh
$ ./test.sh 1 2 3
#Shell 传递参数实例!
#执行的文件名:./test.sh
#第一个参数为:1
#第二个参数为:2
#第三个参数为:3
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
$* 与 $@ 区别:
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
##################################执行输出
$ chmod +x test.sh
$ ./test.sh 1 2 3
#-- $* 演示 ---
#1 2 3
#-- $@ 演示 ---
#1
#2
#3
运算符
算术运算符
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
val=`expr $a \* $b`
echo "a * b : $val"
注意点:
- 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
- 完整的表达式要被
包含,注意这个字符不是常用的单引号,在 Esc 键下边。
- 乘号(*)前边必须加反斜杠()才能实现乘法运算;
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` 结果为 30。 |
- | 减法 | `expr $a - $b` 结果为 -10。 |
* | 乘法 | `expr $a \* $b` 结果为 200。 |
/ | 除法 | `expr $b / $a` 结果为 2。 |
% | 取余 | `expr $b % $a` 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg"
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否为0,不为0返回 true。 | [ -n $a ] 返回 true。 |
str | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n $a ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
file="/var/www/runoob/test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
echo 命令
Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出
命令格式:
echo string
echo "It is a test"
#等价
echo It is a test
#显示转义字符
echo "\"It is a test\""
#等价
echo \"It is a test\"
#显示变量
#read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
read name
echo "$name It is a test"
#显示换行
echo -e "OK! \n" # -e 开启转义
echo "It it a test"
#显示不换行
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
#显示结果定向至文件
echo "It is a test" > myfile
#原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
#显示命令执行结果
echo `date`
printf 命令
printf 命令模仿 C 程序库(library)里的 printf() 程序。
printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。
printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。
printf 命令的语法:
printf format-string [arguments...]
printf的转义序列
序列 | 说明 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 一个字面上的反斜杠字符 |
\ddd | 表示1到3位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示1到3位的八进制值字符 |
echo "Hello, Shell"
printf "Hello, Shell\n"
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
# format-string为双引号
printf "%d %s\n" 1 "abc"
# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"
# 没有引号也可以输出
printf %s abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def
printf "%s\n" abc def
printf "%s %s %s\n" a b c d e f g h i j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n"
##################################
%d %s %c %f 格式替代符详解:
d: Decimal 十进制整数 -- 对应位置参数必须是十进制整数,否则报错!
s: String 字符串 -- 对应位置参数必须是字符串或者字符型,否则报错!
c: Char 字符 -- 对应位置参数必须是字符串或者字符型,否则报错!
f: Float 浮点 -- 对应位置参数必须是数字型,否则报错!
如:其中最后一个参数是 "def",%c 自动截取字符串的第一个字符作为结果输出。
test 命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
数值测试
参数 | 说明 |
---|---|
-eq | 等于则为真 |
-ne | 不等于则为真 |
-gt | 大于则为真 |
-ge | 大于等于则为真 |
-lt | 小于则为真 |
-le | 小于等于则为真 |
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
result=$[num1+num2] # 注意等号两边不能有空格
echo "result 为: $result"
字符串测试
参数 | 说明 |
---|---|
= | 等于则为真 |
!= | 不相等则为真 |
-z 字符串 | 字符串的长度为零则为真 |
-n 字符串 | 字符串的长度不为零则为真 |
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
文件测试
参数 | 说明 |
---|---|
-e 文件名 | 如果文件存在则为真 |
-r 文件名 | 如果文件存在且可读则为真 |
-w 文件名 | 如果文件存在且可写则为真 |
-x 文件名 | 如果文件存在且可执行则为真 |
-s 文件名 | 如果文件存在且至少有一个字符则为真 |
-d 文件名 | 如果文件存在且为目录则为真 |
-f 文件名 | 如果文件存在且为普通文件则为真 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
-b 文件名 | 如果文件存在且为块特殊文件则为真 |
cd /bin
if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
非 与 或
另外,Shell还提供了 非( ! )、与( -a )、或( -o ) 三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。例如:
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
流程控制
if else if
在sh/bash里,如果else分支没有语句执行,就不要写这个else
#语法
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
#写成一行
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
#if else语句经常与test命令结合使用,如下所示:
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi
for循环
#语法
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
#写成一行
for var in item1 item2 ... itemN; do command1; command2… done;
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
for str in 'This is a string'
do
echo $str
done
while 语句
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件
Bash let 命令
#语法
while condition
do
command
done
int=1
while(( $int<=5 ))
do
echo $int
#使用中使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量
let "int++"
done
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
echo "是的!$FILM 是一个好网站"
done
无限循环
while :
do
command
done
#或
while true
do
command
done
#或
for (( ; ; ))
until循环
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
#语法
until condition
do
command
done
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
case
Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令
#语法
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
跳出循环
break命令
break命令允许跳出所有循环(终止执行后面的所有循环)
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
continue
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
#esaccase的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。
done
函数
#定义函数语法
#1. 可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
#2. 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
[ function ] funname [()]
{
action;
[return int;]
}
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
#函数参数 在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值
#注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
Shell 输入/输出重定向
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
#输出重定向 语法
command1 > file1
#######################
who > users #重定向会覆盖文件内容
who >> users #不希望文件内容被覆盖,可以使用 >> 追加到文件末尾
cat users
#输入重定向 语法
command1 < file1
#######################
wc -l users #会输出文件名
wc -l < users #不会输出文件名 因为它仅仅知道从标准输入读取内容
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
command 2 > file
如果希望 stderr 追加到 file 文件末尾,可以这样写:
command 2 >> file
2 表示标准错误文件(stderr)
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
command > file 2>&1
或者command >> file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
command < file1 >file
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
#Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序 语法:
command << delimiter
document
delimiter
#它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
#结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
#开始的delimiter前后的空格会被忽略掉。
wc -l << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
3 # 输出结果为 3 行
cat << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
## 他人笔记
command > file 2>&1
$ command >> file 2>&1
这里的&没有固定的意思
放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符,内置的文件描述符如下
1 => stdout
2 => stderr
0 => stdin
换言之 2>1 代表将stderr重定向到当前路径下文件名为1的regular file中,而2>&1代表将stderr重定向到文件描述符为1的文件(即/dev/stdout)中,这个文件就是stdout在file system中的映射
而&>file是一种特殊的用法,也可以写成>&file,二者的意思完全相同,都等价于
>file 2>&1
此处&>或者>&视作整体,分开没有单独的含义
顺序问题:
find /etc -name .bashrc > list 2>&1
# 我想问为什么不能调下顺序,比如这样
find /etc -name .bashrc 2>&1 > list
这个是从左到右有顺序的
第一种
xxx > list 2>&1
先将要输出到stdout的内容重定向到文件,此时文件list就是这个程序的stdout,再将stderr重定向到stdout,也就是文件list
第二种
xxx 2>&1 > list
先将要输出到stderr的内容重定向到stdout,此时会产生一个stdout的拷贝,作为程序的stderr,而程序原本要输出到stdout的内容,依然是对接在stdout原身上的,因此第二步重定向stdout,对stdout的拷贝不产生任何影响
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1
注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)
Shell 文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
#语法
. filename # 注意点号(.)和文件名中间有一空格
#或
source filename
## test1.sh 文件内容
url="http://www.runoob.com"
###############################
## test2.sh 文件内容
#使用 . 号来引用test1.sh 文件
. ./test1.sh
# 或者使用以下包含文件代码
# source ./test1.sh
echo "菜鸟教程官网地址:$url"
chmod +x test2.sh
./test2.sh
#菜鸟教程官网地址:http://www.runoob.com