Shell Syntax Basic

时间:2021-08-08
本文章向大家介绍Shell Syntax Basic,主要包括Shell Syntax Basic使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Shell Syntax Basic

Variables

shell中并不需要提前声明变量,每次使用的时候自动生成,并且所有变量在默认的情况下都是字符串。Linux对于变量的大小写敏感,因此需要格外注意。

通过 $ 运算符,可以访问变量的内容,声明变量有两种方式:

  • 直接赋值;
var="content in var"
  • read 方法
read var
> type contents here to assign

通常在bash中会使用空格来分割不同的命令、语句,如果希望给变量赋值的时候带一个空格,需要用"..."来包含;同时,如果希望通过变量的值替换 $var 则需要用双引号,而如果不期望替换的话,用单引号或者转义字符。

环境变量 Environmentt Variables

Environment Variable Description
$HOME The home directory of the current user
$PATH A colon-separated list of directories to search for commands
$PS1 A command prompt, frequently $, but in bash you can use some more complex values; for example, the string [\u@\h \W]$ is a popular default that tells you the user, machine name, and current directory, as well as providing a $​ prompt.
$PS2 A secondary prompt, used when prompting for additional input; usually >.
$IFS An input field separator. This is a list of characters that are used to separate words when the shell is reading input, usually space, tab, and newline characters.
$0 The name of the shell script
$# The number of parameters passed
$$ The process ID of the shell script, often used inside a script for gener- ating unique temporary filenames; for example /tmp/tmpfile_$$

通过 man env 可以查看如何通过 export 设置环境变量。

Parameter Variables

如果在调用脚本的时候,带有命令行参数,则会自动生成一些变量,如果没有传递参数,则 $# 返回 0;

Parameter Variable Description
$1, $​2, … The parameters given to the script
$* A list of all the parameters, in a single variable, separated by the first character in the environment variable IFS. If IFS is modified, then the way $* separates the command line into parameters will change.
$@ A subtle variation on $*; it doesn’t use the IFS environment vari- able, so parameters are not run together even if IFS is empty.
#!/bin/sh

salutation=”Hello”

echo $salutation

echo “The program $0 is now running”

echo “The second parameter was $2”

echo “The first parameter was $1”

echo “The parameter list was $*“

echo “The user’s home directory is $HOME”

echo “Please enter a new greeting”

read salutation

echo $salutation

echo “The script is now complete”

exit 0

Output

$ ./try_var foo bar baz 
Hello 
The program ./try_var is now running 
The second parameter was bar 
The first parameter was foo 
The parameter list was foo bar baz 
The user’s home directory is /home/rick 
Please enter a new greeting 
>Sire 
Sire 
The script is now complete 
$

Conditions

Shell 脚本可以检测所有命令行可以激活的命令的返回值,所以每次书写 Shell 脚本的时候带上返回值是很重要的。

The test or [ Command

Shell 语句通过 [ 检查布尔值,在书写的时候,方括号前后必须有空格,可以把 test 和 方括号当作同义词,因为在使用test的时候还会带上空格。如果希望把 if ... then 语句放在同一行,则必须在方括号条件值后面加上一个分号。

#!/bin/sh

if [ -f /bin/bash ]; then
	echo “file /bin/bash exists”
fi

if [ -d /bin/bash ]; then
	echo “/bin/bash is a directory”
		else
	echo “/bin/bash is NOT a directory”
fi

条件类型可以用来做三件事:

  • 字符串比较
String Comparison Result
string1 = string2 True if the strings are equal
string1 != string2 True if the strings are not equal
-n string True if the string is not null
-z string True if the string is null (an empty string)
  • 算数比较
Arithmetic Comparison Result
expression1 -eq expression2 True if the expressions are equal
expression1 -ne expression2 True if the expressions are not equal
expression1 -gt expression2 True if expression1 is greater than expression2
expression1 -ge expression2 True if expression1 is greater than or equal to expression2
expression1 -lt expression2 True if expression1 is less than expression2
expression1 -le expression2 True if expression1 is less than or equal to expression2
! expression True if the expression is false, and vice versa
  • 文件状态比较
File Conditional Result
-d file True if the file is a directory
-e file True if the file exists. Note that historically the -e option has not been portable, so -f is usually used.
-f file True if the file is a regular file
-g file True if set-group-id is set on file
-r file True if the file is readable
-s file True if the file has nonzero size
-u file True if set-user-id is set on file
-w file True if the file is writable
-x file True if the file is executable

Program control

if

#!/bin/sh

echo “Is it morning? Please answer yes or no”

read timeofday

if [ $timeofday = “yes” ]; then

	echo “Good morning”

else

	echo “Good afternoon”

fi

exit 0

Elif

用于给 if 控制符添加第二个条件,请看例子

...
if [ $timeofday = "yesy" ]; then
	echo ...
	
	elif [ $timeof = "no" ]; then
		
		echo ...
else
	echo ...
	exit 1
if
exit 0

当直接敲入回车的时候,此程序会有bug,因为没有字符串与 “yes” 进行比较,因此最好把 $timeofday 用双引号扩起来,这样就必有一个字符串与 “yes” 进行比较了。

For

用for巡护眼可以在一个字符串集合的基础上,控制循环,这个集合通常是一堆文件名。

for variable in values
do
	statements
done

在使用 for 循环的时候,使用通配符,可以大幅度的简化程序,并且不丧失可读性。

#!/bin/sh

for file in $(ls f*.sh); do
	lpr $file
done

exit 0

while

当不知道循环次数的时候,一般没法用 for 循环,而要使用 while 循环;

while condition do
	statements
done
=========================================================================================
#!/bin/sh
echo "Enter password"
read trythis 

while [ "$trythis" != "secret" ]; do
	echo "sorry, try again"
	read trythis
done
exit 0

case statement

#!/bin/sh

echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
	yes)	echo “Good Morning”;;
	no)	echo “Good Afternoon”;;
	y) 	echo “Good Morning”;;
	n)		echo “Good Afternoon”;;
	
	================================================
	
	yes | y | Yes | YES )	echo "Good morning";;
	n* | N* )	echo "Good Afternoon";;
	* )	echo "Sorry, answer not recognized";;
	
	================================================
	
	[yY] | [Yy][Ee][Ss] ) ...
	[nN]* )	echo "Good Afternoon";;
	
	================================================
	
	*)		echo “Sorry, answer not recognized”;;
esac

exit 0

Lists

The "AND" List

statement_1 && statement_2 && statement_3 && ...

且列表允许用户执行一系列命令,仅当之前的命令全部执行了,才可以执行下一个(从最左边开始)。

The "OR" List

statement_1 || statement_2 || ...

从左至右执行,直到有一个执行成功,则不再执行。下一个命令如果想要执行,则上一个命令必须失败。

Functions

在使用一个函数之前,必须要首先定义它,定义的方式与其他语言差不多:

#!/bin/bash

foo() {
	echo "Function foo is executing!"
}

foo

exit 0

当唤醒一个函数的时候,$*, $@, $#, $1$ 等变量会被函数变量替代,当函数执行结束,又会恢复到原有值。使用 return 关键字可以让函数返回数值,若希望函数返回字符串,要们新建一个字符串用于存储返回字符串,要么使用 echo 语句:

foo(){
	echo STRING_HERE
}
...
result="$(foo)"

函数返回值

下面的例子说明了如何传递值给函数,并且返回结果。

#!/bin/sh

yes_or_no() {
	echo "Is this your name $* ?"
	while true
	do
		echo -n "Enter yes or no: "
		read x
		case "$x" in
			y | yes ) return 0;;
			n | no ) return 1;;
			* ) echo "Answer yes or no"
		esac
	done
}

echo "Original parameters are $*"

if yes_or_no "$1"
then
	echo "Hi, $1, nice name"
else
	echo "Never mind"
fi
exit 0

Commands built into the shell

You can execute two types of commands from inside a shell script. There are “normal” commands that you could also execute from the command prompt (called external commands), and there are “built-in” commands (called internal commands), as mentioned earlier. Built-in commands are implemented internally to the shell and can’t be invoked as external programs. However, most internal commands are also provided as standalone programs — this requirement is part of the POSIX specification. It generally doesn’t matter if the command is internal or external, except that internal commands execute more efficiently.

Two Useful Commands and Regular Expressions

Find 命令

  • -name
    按照文件名查找文件。
    find /dir -name filename 在/dir目录及其子目录下面查找名字为filename的文件
    find . -name "*.c" 在当前目录及其子目录(用“.”表示)中查找任何扩展名为“c”的文件
  • -type
    查找某一类型的文件,诸如:
    b - 块设备文件。
    d - 目录。
    c - 字符设备文件。
    p - 管道文件。
    l - 符号链接文件。
    f - 普通文件。
    find /etc -type d –print 在/etc目录下查找所有的目录
    find . ! -type d –print 在当前目录下查找除目录以外的所有类型的文件
    find /etc -type l –print 在/etc目录下查找所有的符号链接文件
  • -size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
    find . -size +1000000c –print 在当前目录下查找文件长度大于1 M字节的文件
    find /home/apache -size 100c –print 在/home/apache目录下查找文件长度恰好为100字节的文件
    find . -size +10 –print 在当前目录下查找长度超过10块的文件(一块等于512字节)
  • -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
    find / -name "CON.FILE" -depth –print 它将首先匹配所有的文件然后再进入子目录中查找
  • -mount:在查找文件时不跨越文件系统mount点。
    find . -name "*.XC" -mount –print 从当前目录开始查找位于本文件系统中文件名以XC结尾的文件(不进入其他文件系统)
  • -follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。
  • -mtime -n +n
    按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。
    find / -mtime -5 –print 在系统根目录下查找更改时间在5日以内的文件
    find /var/adm -mtime +3 –print 在/var/adm目录下查找更改时间在3日以前的文件

Find with xargs

find . -type f -print | xargs file 查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件

find / -name "core" -print | xargs echo "" >/tmp/core.log 在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中:

find . -type f -print | xargs grep "hostname" 用grep命令在所有的普通文件中搜索hostname这个词

find ./ -mtime +3 -print | xargs rm -f –r 删除3天以前的所有东西 (find . -ctime +3 -exec rm -rf {} ;)

find ./ -size 0 | xargs rm -f & 删除文件大小为零的文件

find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。

Grep - global search regular expression and print out the line

grep [OPTIONS] PATTERN [FILE...] 
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
  • ^pattern: 以 pattern 开头的行;
  • pattern$: 以 pattern 结尾的行;
  • patte.n: 匹配一个非换行符的字符;
  • pat*n: 匹配零个或多个先前字符;
  • [pattern]: 匹配一个指定范围内的字符;
  • [^pattern]: 匹配一个不在指定范围内的字符;
  • \<pattern: 匹配包含以 pattern 开头的单词 的行;
  • \>: 锚定单词的结束;

可选参数

  • -?:同时显示上下?的行;
  • -c:只打印匹配的行术,不限时匹配的内容;
  • -h:搜索多个文件时,不显示匹配文件名前缀;
  • -n:在匹配行的前面打印行号;
  • -s:不限时不存在或者无法读取的错误信息;
  • -v:只显示不匹配的行;

例子

ls -l | grep '^a' 通过管道过滤ls -l输出的内容,只显示以a开头的行。

grep 'test' d* 显示所有以d开头的文件中包含test的行。

grep 'test' aa bb cc 显示在aa,bb,cc文件中匹配test的行。

grep '[a-z]' aa 显示所有包含每个字符串至少有5个连续小写字符的字符串的行。

grep 'w(es)t.*' aa 如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.),这些字符后面紧跟着另外一个es(),找到就显示该行。如果用egrep或grep -E,就不用""号进行转义,直接写成'w(es)t.'就可以了。

grep -i pattern files :不区分大小写地搜索。默认情况区分大小写

grep -l pattern files :只列出匹配的文件名,

grep -L pattern files :列出不匹配的文件名,

grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’),

grep -C number pattern files :匹配的上下文分别显示[number]行,

grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,

grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。

原文地址:https://www.cnblogs.com/CharminZh/p/15115219.html