roboslyq的技术专栏 JavaEE Coder,micro service

shell

2019-05-06
roboslyq


什么是shell

两重含义:

1、壳,此时shell是一个用 C 语言编写的应用程,是用户与内核实现交互的窗口

2、一门解释性的脚本编程语言

3、具体的shell源码,常以.sh结尾

shell程序第1行

最常见的是以下面这个字符串开头:

#!/usr/bin/sh

在 shell 脚本, #! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 解释器。 #! 被称作shebang(也称为 Hashbang )。 所以,你应该会在 shell 中,见到诸如以下的注释:

指定 sh 解释器

#!/bin/sh

指定 bash 解释器

#!/bin/bash

常见的shell如下:

名称 描述
sh 即 Bourne Shell。sh 是 Unix 标准默认的 shell
bash 即 Bourne Again Shell。bash 是 Linux 标准默认的 shell。即bash是sh的扩展,有更强大的语法功能
fish 智能和用户友好的命令行 shell。
xiki 使 shell 控制台更友好,更强大。
zsh 功能强大的 shell 与脚本语言。

shell的语法坑

当你从其它语言转过来的时候,一定会不太适应shell的几个语法坑

对空格的使用

  • ​ 在if else语法中,if与后面的表达式必须有空格隔开,这对于熟悉其他语言的程序员来说很容易将其忽略,导致面对语法错误的提示百思不得其解。

  • if [ expression ]
    then
       Statement(s) to be executed if expression is true
    fi
    

如果then与if在同一行,则需要分号分割.

if [ expression ];then
   Statement(s) to be executed if expression is true
fi

多元素表达

在表达多个元素时,元素之间是采用空格个来分隔,比如:

# 定义数组
array_name=(value0 value1 value2 value3)

#函数参数
printf "%d %s\n" 1 "abc"

为什么不能使用逗号呢?估计是历史原因吧。

变量定义

定义变量时,变量名和等号之间不能有空格!!!

myNum =10   # 错误,等号前有空格 
myNum=10	# 正确

注释

# 单行注释

:<<EOF
 多行注释
EOF

###################
#注释测试
###################

通常我们可以将单行注释#作为多行注释使用。可以达到多行注释的效果

echo

# 输出普通字符
echo "hello,world"

# 输出变量
val="hello,world"
echo "${val}"

#输出换行符 ,注意-e 是开启转义,不能少。少了就自动换行
echo -e "YES\nNO" 

# 输出重定向
echo "test" > test.txt

# 输出执行结果(例如当前路径在“/home/roboslyq”,则下面语句会输出/home/roboslyq)
echo `pwd`

变量

弱变量类型语言

跟许多程序设计语言一样,你可以在 bash 中创建变量。 Bash 中没有数据类型,bash 中的变量可以保存一个数字、一个字符、一个字符串等等。同 时无需提前声明变量,给变量赋值会直接创建变量。

声明变量 访问变量的语法形式为: ${var} 和 $var 。 变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,所 以推荐加花括号。

#!/usr/bin/env bash

################### 声明变量 ###################
name="world"
echo "hello ${name}"
# Output: hello world

################### 只读变量 ###################
rword="hello"
echo ${rword}
# Output: hello
readonly rword
# rword="bye"  # 如果放开注释,执行时会报错

################### 删除变量 ###################
dword="hello" # 声明变量
echo ${dword} # 输出变量值
# Output: hello

unset dword # 删除变量
echo ${dword}
# Output: (空)

字符串

在shell中,可以使用单引号,双引号或者不使用引号

其中单引号里的字符串不会支持变量连接,而双引号支持变量链接。例如:

hello='hello,world'
'a ${hello}'  # 结果是a ${hello}
'${hello}'    # 结果是 hello,world
"a,${hello}"  # 结果是a,hello,world

双引号可以包含双引号,只需要转义即可。但单引号不行。

获取字符串长度

hello="hello,world"
echo ${#hello} # 输出11

截取字符串

hello="hello,world"
echo ${hello:2:2} # 输出ll,从第 3(编号从0开始,所以2对应第3个字符) 个字符开始,截取 2 个字符长度

查找字符串所有位置

hello="hello,world"
echo ${hello:2:2}
echo `expr index ${hello} 'll' `

示例汇总

#!/usr/bin/env bash

################### 单引号和双引号 ###################
################### 拼接字符串 ###################
# 使用单引号拼接
name1='white'
str1='hello, '${name1}''
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}

# 使用双引号拼接
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black

################### 获取字符串长度 ###################
text="12345"
echo "${text} length is: ${#text}"
# Output:
# 12345 length is: 5

################### 获取字符串长度 ###################
text="12345"
echo ${text:2:2}
# Output:
# 34

################### 查找子字符串 ###################
text="hello"
echo `expr index "${text}" ll`
# Output:
# 3

################### 截取关键字左边内容(保留右边) ###################
full_branch="feature/1.0.0"
branch=`echo ${full_branch#feature/}`
echo "branch is ${branch}"

################### 截取关键字右边内容(保留左边) ###################
full_version="0.0.1-SNAPSHOT
version=`echo ${full_version%-SNAPSHOT}`
echo "version is ${version}"

################### 判断字符串中是否包含子字符串 ###################
result=$(echo "${str}" | grep "feature/")
if [[ "$result" != "" ]]; then
    echo "feature/ 是 ${str} 的子字符串"
else
    echo "feature/ 不是 ${str} 的子字符串"
fi

数组

定义

# 创建数组:小括号  然后是中括号表时下标并初始化变量值
array=([0]=1 [1]=2)

# 数组取值
echo ${array[0]}

# 获取数据所有元素
echo ${array[*]}
echo ${array[@]}

# 元素循环遍列(for语句)
for element in ${array[@]};do
  echo $element
 done
 
#记数器i遍列 
for i in $(seq 0 ${array[@]});do
   echo ${array[i]}
 done

MAP使用

declare -A SEGMENT_SEQ=(["NA"]="01" ["AL"]="02")
echo ${SEGMENT_SEQ["NA"]}
# 会输出01

# 或者不需要declare也行
SEGMENT_SEQ=(["NA"]="01" ["AL"]="02")
echo ${SEGMENT_SEQ["NA"]}
# 会输出01


普通操作符

表达式计算,注意:条件表达式要放在方括号之间,并且要有空格,例如: [$x==$y] 是错误的,必须写 成 [ $x == $y ]

#!/usr/bin/env bash

x=10
if [[ -n $1 ]]; then
    x=$1
fi

y=20
if [[ -n $2 ]]; then
    y=$2
fi

echo "x=${x}, y=${y}"

val=`expr ${x} + ${y}`
echo "${x} + ${y} = $val"

val=`expr ${x} - ${y}`
echo "${x} - ${y} = $val"

val=`expr ${x} \* ${y}`
echo "${x} * ${y} = $val"

val=`expr ${y} / ${x}`
echo "${y} / ${x} = $val"

val=`expr ${y} % ${x}`
echo "${y} % ${x} = $val"

if [[ ${x} == ${y} ]]; then
    echo "${x} = ${y}"
fi
if [[ ${x} != ${y} ]]; then
    echo "${x} != ${y}"
fi

#  Execute: ./operator-demo.sh
#  Output:
#  x=10, y=20
#  10 + 20 = 30
#  10 - 20 = -10
#  10 * 20 = 200
#  20 / 10 = 2
#  20 % 10 = 0
#  10 != 20

#  Execute: ./operator-demo.sh 10 30
#  Output:
#  x=10, y=30
#  10 + 30 = 40
#  10 - 30 = -20
#  10 * 30 = 300
#  30 / 10 = 3
#  30 % 10 = 0
#  10 不等于 30

			

let和expr

# 要想达到预期结果,用下列三种方法:

# let不需要$符号
let "var+=1"  

#$(()),注意不是{}
var=$((var+1))

var=$[$var+1] 

var=`expr $var + 1`#注意加号两边的空格,否则还是按照字符串的方式赋值。

For循环

与C语言很像:

for arg in elem1 elem2 ... elemN
do
### 语句
done

写成一行,用分号分割:

for arg in elem1 elem2 ... elemNdo
### 语句
done

同时也支持正常的像java高级语言一样的for循环

for (( i = 0; i < 10; i++ )); do
echo $i
done

exp:

#!/usr/bin/env bash

################### for 语句 ###################
echo "print 0 to 9"
for (( j = 0; j < 10; j ++ )); do
    echo ${j}
done
#  Output:
#  print 0 to 9
#  0
#  1
#  2
#  3
#  4
#  5
#  6
#  7
#  8
#  9

################### for in 语句 ###################
echo "print 1 to 5"
for i in {1..5}; do
    echo ${i};
done
#  Output:
#  print 1 to 5
#  1
#  2
#  3
#  4
#  5

################### for in 语句遍历文件 ###################
DIR=/home/zp
for FILE in ${DIR}/*.sh; do
    mv "$FILE" "${DIR}/scripts"
done
# 将 /home/zp 目录下所有 sh 文件拷贝到 /home/zp/scripts

while循环

while [[ condition ]]
do
### 语句
done
start=0
end=50
while [ "$start" -le "$end" ]; do
    printf '%s\n' "$start"
    start=$((start+1))
done

Until循环

i=0
until [ ${i} -gt 5 ]; do
	echo ${i}
	#i=`expr ${i} + 1`
	let "i++"
done

#输出如下:
0
1
2
3
4
5

文件操作

if [ -d '/home/test' ];then
	echo "y"
else 
	echo "n"
fi


下一篇 优秀项目收集

Comments

Content