Linux Shell 实践
快捷键
Ctrl+r快速查找历史命令Ctrl+l清理控制台屏幕
移动光标
Ctrl+a移动光标到行首Ctrl+e移动光标到行尾Alt+Left Arrow移动光标到上一个单词Alt+Right Arrow移动光标到下一个单词
删除字符
Ctrl+u删除光标之前的内容Ctrl+k删除光标之后的内容Ctrl+w删除光标前面的一个单词
进程
Ctrl+d退出。等同于exit命令Ctrl+z当前运行的程序后台运行。如果一步到位,可以在命令后面加&
重定向
- 执行时的错误信息输出到文件(
2>)hello 2> log.error$ cat log.error -bash: hello: 未找到命令 - 执行时的所有信息都输出到文件(
&>)echo hello &> log.info$ cat log.info hello - 创建一个文件并写入内容(
> filename <<EOF)cat > hello.sh << EOF #!/bin/bash echo hello EOF
变量
变量赋值
- 执行结果保存到变量(
$()``)var1=$(pwd) var2=`pwd` - 整数四则运算(
let)let n=10-3+4/2 echo $n9
变量引用
${var}大部分情况可省略为$varstr="hello world" echo $str ${str}123
变量作用范围
- 默认只在当前shell中生效
$ str="hello world" $ echo $str hello world $ bash $ echo $str $ exit $ echo $str hello world - 四种执行模式运行
$ vim test.sh #!/bin/bash echo $str $ chmod u+x test.sh $ bash test.sh $ ./test.sh $ source test.sh hello world $ . test.sh hello world - 导出变量(
export),父进程定义的变量子进程可见。$ export str $ bash test.sh hello world $ source test.sh hello world - 移除变量(
unset)$ unset str $ echo $str
环境变量配置文件
- /etc/profile
- /etc/profile.d
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
su - root 执行顺序
- /etc/profile
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
su root 执行顺序
- ~/.bashrc
- /etc/bashrc
修改后的配置文件在当前Shell生效
source ~/.bashrc
环境变量
env查看命令$PATH命令的搜索路径$PS1bash提示符
预定义变量
$?上一个命令执行的错误码$ ifconfig $ echo $? 0 $ ifconfig eth $ echo $? 1$$当前进程ID$ echo $$ 26102$0当前进程名$ echo $0 -bash
位置变量 $1 $2 $3 ... $N
vim test.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12-DEFAULT_VALUE}
if [ -z ${12} ]
then
echo "NULL"
else
echo "NOT NULL"
fi
$ chmod u+x test.sh
$ ./test.sh 1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11 DEFAULT_VALUE
NULL
$ ./test.sh 1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 7 8 9 10 11 12
NOT NULL
- 位置值超过9后需要使用花括号
${N} - 没有传入值变量为空,可以给一个默认值
${N-DEFAULT_VALUE}SHOW_LABELS=${1:-true}
数组
- 定义数组
ips=(10.0.0.1 10.0.0.2 10.0.0.3) - 显示所有数组元素
$ echo ${ips[@]} 10.0.0.1 10.0.0.2 10.0.0.3 - 数组元素个数
$ echo ${#ips[@]} 3 - 数组取值
$ echo ${ips} 10.0.0.1 $ echo ${ips[0]} 10.0.0.1 $ echo ${ips[2]} ${ips[-1]} 10.0.0.3 10.0.0.3
引用
- 单引号(完全引用)
$ name=wjj $ echo 'Hello $name!' Hello $name! - 双引号(不完全引用)
$ name=wjj $ echo "Hello $name!" Hello wjj! - 反引号(执行命令)
$ echo `pwd` /root
运算符
- 赋值运算符
$ let n=4+5 $ echo $n 9 $ ((n=4+5)) $ echo $n 9 $ ((n++)) $ echo $n 10 $ echo $((3+4)) 7 - 算术运算符(+ - * / ** %)
$ expr 4 + 5 9
表达式
序列表达式 {START..END[..INCREMENT]}
$ echo {1..3}
1 2 3
$ echo {1..5..2}
1 3 5
$ echo {3..1}
3 2 1
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
echo {01..3}
01 02 03
echo file{1..3}.jpg
file1.jpg file2.jpg file3.jpg
if
判断变量为空-z
下面是判断 $1 和 $2 任意一个为空则为 True
if [ -z $1 ] || [ -z $2 ]; then
fi
判断文件是否存在-f
if [ -f $1 ]; then echo “file exist” fi
for
遍历数字范围
for i in {1..3}; do echo $i; done
1
2
3
函数
传入数组变量 "${VAR[*]}" 一定要加 "
f(){
arr=$1
}
ARR=(1 2 3)
f "${ARR[*]}"
虽然 echo "${ARR[*]}" 和 echo "${ARR[@]}" 的显示结果都一样,但传函数参数的效果确不一样。
测试代码
f(){
local app_name=$1
local platforms=$2
local version=$3
echo $app_name $version
for platform in $platforms
do
echo "Platform: $platform"
done
}
APP_NAME=yolo
PLATFORMS=(arm64 x86_64 i386)
VERSION=1.0.0
f $APP_NAME "${PLATFORMS[@]}" $VERSION
echo '----------------'
f $APP_NAME "${PLATFORMS[*]}" $VERSION
执行结果
yolo x86_64
Platform: arm64
----------------
yolo 1.0.0
Platform: arm64
Platform: x86_64
Platform: i386