Shell基础学习

119 阅读4分钟
#!/bin/bash

echo "Hello shell"

#!!!变量名和等号之间不能有空格
#命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
#中间不能有空格,可以使用下划线 _。
#不能使用标点符号。

name="xiaoming"
readonly name
echo "my name is ${name}!"

#获取字符串长度
echo ${#name}

#将当前目录的文件名循环出来。
#for file in $(ls ./)

for file in `ls ./`;do
echo $file
done

#$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
echo $1


#$* 与 $@ 区别:
#相同点:都是引用所有参数。
#不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 123,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
# ?? $*不带 “” 的时候得到的也是 "1" "2" "3"

for i in $* ; do
echo $i # "123"
done

for i in "$@" ; do
echo $i  # "1" "2" "3"
done

#数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小

#方法1
array=(a b c)

#方法2
array1[0]=e
array1[1]=f
array1[2]=g
echo ${array[2]} #a
echo ${array1[2]} #f

#获取数组长度的方法与获取字符串长度的方法相同
echo "数组元素个数为${#array[*]}"

#默认array指的是array[0],即${array} == ${array[0]},${#array} == ${#array[0]}
#要获取单个下标值就得使用 array[1], 获取全部就用${#array[*]} 或 ${#array[@]}
#原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
#  " ` " 是markdown语法中代码段的标记符号,不是引号
# + 号两边一定要有空格
#或者使用$[2*3] ,不支持$[2^3]高级运算符

val=`expr 1 + 2` 
val1=$[2*3] 
echo $val   # 3
echo $val1  # 6

#关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
#下表列出了常用的关系运算符,假定变量 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等于b"
else
echo "a不等于b"
fi


##printf
# "\n"换行
# 占位符:"%s":字符串  "%c":字符 "%d":整型  "%f":浮点数
# %-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
# .2 指保留2位小数。

printf "%-10s %-s\n" 姓名 成绩
printf "%-10s %-.2f\n" 小明 60.50900 #60.51 会四舍五入
printf "%-10s %-.2f\n" 小红 95       #95.00 会补齐0
printf "%-10s %-.2f\n" 小花 110.5    #110.50
printf "this! \a\n"
#!/bin/bash

#shell中数值的判断符

# -eq : ==
# -ne : !=
# -gt : >
# -ge : >=
# -lt : <
# -le : <=


a=10
b=10
#判断数值一定要使用 test ,不然shell没法识别
if test $a -eq $b
then
echo "a = b"
else
echo "a != b"
fi

# $[] 中执行基本的算数运算
num=$[2*3]
echo $num  # 6
echo "sum = $[a+b]" #sum = 20


#字符串判断符

# =  等于
# !=  不等
# -z 字符串   字符串长度为0则为真
# -n 字符串   字符串长度不为0则为真


c="ccc"
if test -n $c
then
echo "c长度 > 0"
fi

#文件判断符
#-e 文件名    如果文件存在则为真
#-r 文件名    如果文件存在且可读则为真
#-w 文件名    如果文件存在且可写则为真
#-x 文件名    如果文件存在且可执行则为真
#-s 文件名    如果文件存在且至少有一个字符则为真
#-d 文件名    如果文件存在且为目录则为真
#-f 文件名    如果文件存在且为普通文件则为真
#-c 文件名    如果文件存在且为字符型特殊文件则为真
#-b 文件名    如果文件存在且为块特殊文件则为真

cd /bin
if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
fi


#控制流

##for循环
#支持数字
for v in 1 2 3
do
echo $v
done
# 1
# 2
# 3

#不支持循环数组array=(1 2 3),只会打印第一个值 1
array=(1 2 3)
for v in $array
do
echo 1
done
# 1


#支持字符串
for str in xiao ming
do
echo $str
done
# xiao
# ming

#!/bin/bash

#$? 仅对其上一条指令负责,一旦函数返回后其返回值没有立即保存入参数,那么其返回值将不再能通过 $? 获得。
funcA() {
    a=`expr 1 + 2`
    return $a
}
funcA
echo $?  # 3

funcB(){
    b="xiaohua"
    echo $b
}
funcB
echo $? # 0 上一次语句没有return时,$? 为0,表示上一次正确执行

funcC  # funcC: command not found  按序执行,代码前未定义的方法找不到
funcC(){
    c="xiaoming"
    return $c
}

funcC  #正确执行

echo $?  #报错:numeric argument required 255 答:返回值只能是数字(0-255)
funcD(){
    d="xiaomao"
}
echo $d  # 空白  funcD未执行,d未创建
funcD
echo $d  # xiaomao


#read 获取键盘的输入
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
#!/bin/bash

#s.sh 如下
#   #!/bin/bash
#   url="[www.baidu.com](http://www.baidu.com/)"

source ./s.sh  #或者. ./s.sh 第一个点是引用的意思,注意空格
echo $url
# [www.baidu.com](http://www.baidu.com/)


# 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 之间的内容作为输入。

## 输出重定向 >
# commond > file  将会替换 file 里的内容
# commond >> file 追加到原有内容后边

who > out.txt
# xx    ttys000  Mar 23 19:35

who >> out.txt
# xx    ttys000  Mar 23 19:35
# xx    ttys000  Mar 23 19:35

# cat 查看文件里的内容
cat out.txt
# xx    ttys000  Mar 23 19:35
# xx    ttys000  Mar 23 19:35



## 输入重定向  <  (不会影响到file 文件)
#会输出文件名
wc -l out.txt
# 2 out.txt

#输入重定向到 file ,不会输出文件名,因为它仅仅知道从标准输入读取内容
wc -l < out.txt
# 2


## /dev/null
##  如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null
# command > /dev/null
who > /dev/null

# /dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
#   如果希望屏蔽 stdout 和 stderr,可以这样写:
# command > /dev/null 2>&1
who > /dev/null 2>&1


#输入 EOF .. EOF之间的内容,EOF可以是其他字段
cat << EOF
    hello
    world
EOF
# hello
# world

#将输入内容追加写入 file
cat << EOF >> out.txt  # 用 > 会替换
    hello
    world
EOF
# xx    ttys000  Mar 23 19:35
# xx    ttys000  Mar 23 19:35
# hello
# world