shell基本语法-程序员宅基地

技术标签: python  shell  操作系统  

shell初识



shell介绍

shell是一个用c语言编写的应用程序,是用来和linux内核打交道的。比如我们在终端输入ls,那么shell就会帮我们把命令翻译成内核可以识别的指令,从而访问内核所提供的服务。

shell脚本

shell脚本指的是shell可以识别的脚本程序。shell和shell脚本之间的关系就类似于python解释器和py文件之间关系一样,一个是脚本解释器,一个是脚本。只不过为了方便,我们把shell就当成shell脚本了,但实际上shell和shell脚本是两码事。

shell环境

Shell 编程跟 java、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,我们只需要知道两个即可:
    Bourne Shell,也就是我们一般会在shell脚本的第一行写上#!/bin/sh
    Bourne Again Shell,也就是我们一般会在shell脚本的第一行写上#!/bin/bash

这两种方式一般区分的不是特别明显,因此些#!/bin/sh或者#!/bin/bash都行。
但是真要说区别的话,这两者之间有什么区别呢?

对于#!/bin/sh来说,如果中间的代码出现了错误,那么后面的代码不会执行。
但如果是#!/bin/bash的话,中间代码出现了错误,后面的代码仍然会执行

为什么会出现这样的错误呢?
因为sh一般设成bash的软链,在一般的linux系统中,使用#!/bin/sh相当于#!/bin/bash --posix
所以,sh跟bash的区别,实际上就是bash有没有开启posix模式的区别

所以,可以预想的是,如果第一行写成 #!/bin/bash --posix,那么脚本执行效果跟#!/bin/sh是一样的

第一个shell脚本

我们来写一个shell脚本吧,当然啦,必须是hello world

#!/bin/sh
echo hello world
echo "hello world"

# 解释一下,第一行表示我们指定的shell解释器,注意如果没有这一行,会使用默认的解释器
# 但是一般情况下,我们会指定为#!/bin/sh 或者#!/bin/bash
# 第二行和第三行表示输入hello world,区别就是没有加上双引号,这里加与不加均可,但是一般我们都加上。
# 这里的#表示注释,echo类似于python中的print。

shell脚本以.sh结尾,直接执行即可。但是可能会报错,显示没有权限,这时候通过chmod 755 xx.sh赋予权限即可执行。

1229382-20190728204307074-2049862626.png



shell变量


定义和使用变量

变量的定义规则和平常的编程语言是一样的,使用字母数字下划线,并且开头不能是数字。
但是需要注意的一点是:等号之间不能有空格,比如在python中,定义一个变量可以是name = "satori",并且pep8建议等号之间要空格,看起来更工整,但是shell脚本里面这么定义是不可以的,等号之间不可以有空格,因此要这么定义name="satori"
#!/bin/sh
name="mashiro"
age=16

# 如何打印变量呢?通过$变量名 的方式
echo "name is $name,age is ${age}"
# 但是注意到我们在打印age的时候加上了{}
# 其实加不加都无所谓的,但是我们最好还是加上
# 为什么呢?比如说$nameaaa,这里我想打印name在连接上aaa,但如果这样的话会把nameaaa当成一个整体
# 而这个变量显然没有被定义,因此如果我们加上{}就不会出现这个问题了。${name}aaa,就会输出mashiroaaa
# 这里name后面是逗号,所以没事

1229382-20190728204313888-1685723989.png

对于一些整型、字符型的变量,就不用说了。我们还可以嵌入一些命令`

#!/bin/sh

echo "下面我要创建文件了"
# 创建一个文件,shell会逐行执行,执行到这里会创建一个文件。
# 在哪里创建呢?会在当前shell脚本所在的目录里面创建
# 在终端里面执行的命令是可以直接放到shell里面来的
touch "fuck_shanshan.txt"

# 给一个变量赋值,我们也可以将命令执行的结果赋值给一个变量
# 注意到pwd会打印当前的工作区,所以我们这里是``,表示执行原生的命令,将命令的结果赋值给work_dir
# 如果是"pwd",那么表示将pwd这三个字符赋值给work_dir
work_dir=`pwd`
echo "我当前的工作区是:${work_dir}"

1229382-20190728204320791-1354714642.png


只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

#!/bin/bash 

v="哈哈哈"
readonly v  # 设置为只读变量
echo "${v}"  # 可以访问

v="咯咯咯"  # 尝试修改 

1229382-20190728204327770-2130335021.png


删除变量

使用 unset 命令可以删除变量,直接unset 变量名 即可,但是unset不能删除只读变量

1229382-20190728204337109-677888063.png


变量类型

运行shell时,会同时存在三种变量:

  • 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  • 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  • 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

Shell 字符串

字符串是shell编程中最常用的数据类型(话说除了数字和字符串,也没啥其他类型好用了),字符串可以使用单引号、也可以使用双引号,也可以不使用引号,一般我们使用双引号即可。
  • 拼接字符串

    #!/bin/bash
    name="古明地觉"
    where="东方地灵殿"
    # 多个字符串直接拼接即可之间
    # "a""b""c"  --> abc
    echo "${name}""来自于""${where}"

    1229382-20190728204346310-763879262.png

  • 获取字符串长度

    使用#即可

    #!/bin/bash
    name="古明地觉"
    echo "${#name}"

    1229382-20190728204353536-283588286.png

    也可以看出,这里是用字符来计算的,不是用字节来计算的。

  • 提取子字符串

    #!/bin/sh
    
    string="helloworld"
    echo "${string:1}"
    echo "${string:1:4}"

    1229382-20190728204402119-81563040.png

    变量后面加上:,即可提取子字符串,string:1:4表示从索引为1的位置开始取,取4个,注意shell里面所以也是从0开始的。如果是string:1的话,那么会从索引为1的位置取到结尾

    #!/bin/sh
    
    string="helloworld"
    echo "这个会输出啥嘞,${string:100}"  # 这里表示从索引为100的位置取到结尾
    echo "${string:1:100}"  # 从索引为1的位置开始,取100字符

    1229382-20190728204409711-1570208734.png

  • 字符串的截取(补充)

    #号截取,删除左边字符,保留右边字符。

    var="http://www.bilibili.//com"
    echo "${var#*//}"  
    # var表示的是变量,#是运算符,表示删除var中右边的字符,*//表示以第一个//结尾的任意字符
    
    # 所以结果是www.bilibili.//com

    ##号截取,删除左边字符,保留右边字符

    var="http://www.bilibili.//com"
    echo "${var##*//}" 
    # 和#的区别就是,##类似于正则中的贪婪模式,如果是##,那么*//表示最后一个以//结尾的任意字符
    # 所以结果是com

    %号截取,删除右边字符,保留左边字符

    var="http://www.bilibili.//com"
    echo "${var%//*}"   
    # 和#正好相反,删除右边的字符,以//开头的任意字符
    # 所以结果是http://www.bilibili.

    %% 号截取,删除右边字符,保留左边字符

    var="http://www.bilibili.//com"
    echo "${var%%//*}" 
    # 不用我说了
    # 结果是http:

    从左边第几个字符开始,及字符的个数

    var="http://www.bilibili.//com"
    echo "${var:0:6}"
    # http:/

    从左边第几个字符开始,一直到结束。

    var="http://www.bilibili.//com"
    echo "${var:6}"
    # /www.bilibili.//com

    从右边第几个字符开始,及字符的个数

    var="http://www.bilibili.//com"
    echo ${var:0-7:3}
    # 其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。
    # 输出结果是i./

    从右边第几个字符开始,一直到结束。

    var="http://www.bilibili.//com"
    echo ${var:0-7}
    # i.//com

shell注释

开始就已经提过了
以 # 开头的行就是注释,会被解释器忽略。但这是单行注释,此外还有多行注释

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

EOF 也可以使用其他符号:

:<<'
注释内容...
注释内容...
注释内容...
'

:<<!
注释内容...
注释内容...
注释内容...
!


shell脚本传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
类似于python里面的sys.argv,sys.argv[0]表示文件名,sys.argv[1]表示第一个参数。。。。依次类推
#!/bin/sh
name="$1"
age="$2"
gender="$3"

echo "name is ${name},age is ${age},gender is ${gender}"

1229382-20190728204559557-1333408071.png

可以看到$0 $1 $2等等都是系统的保留变量,那么除此之外,还有哪些保留的变量呢?
  • $#:传递到脚本的参数个数
  • $*:显示向脚本传递的所有参数
  • $@:显示向脚本传递的所有参数,这个和$*有什么区别呢?后面举例说明
  • $$:脚本运行的当前进程的id号
  • $!:后台运行的最后一个进程的id号
  • $?:显示最后命令的退出状态,如果没有错误则为0,其他的值表示有错误
#!/bin/bash

echo "shell传递参数实例"
echo "一共传过来$#个参数"
echo "第一个参数为$0"  # 如果我们设置了 xx="$0",那么这里要写${xx},如果直接写的话,直接$0即可,切记不可以这么写:${$0}
echo "传递到所有脚本的所有参数是:$*"
echo "传递到所有脚本的所有参数是:$@"
echo "脚本运行的当前进程的id号是:$$"
echo "后台运行的最后一个进程的id号是:$!"
echo "程序的退出状态,0是正常退出哦。状态为:$?"

1229382-20190728204607812-1037364753.png

那么$*和$@到底有神马区别,假设我们传递了1 2 3 4 5这五个参数,那么$*的话,等价于"1 2 3 4 5"(传递了一个参数),$@等价于传递了"1""2""3""4""5"(传递了五个参数)

我们不妨检测一下,这里使用了for循环,我们后面会介绍

#!/bin/bash

echo "--\$*演示--"  # \表示转义字符
for i in "$*";do
  echo "${i}"
done

echo "--\$@演示--"
for i in "$@";do
  echo "${i}"
done

1229382-20190728204614881-1176775332.png



shell数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

定义数组

在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为,数组名=(值1 值2 ... 值n)

例如array_name=(value0 value1 value2 value3)
array_name=(
value0
value1
value2
value3
)

读取数组

读取数组元素值的一般格式是:${数组名[下标]}
例如:value=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:echo ${array_name[@]}
#!/bin/sh
arr=("mashiro" 16 "东方地灵殿")
echo "${arr[0]}今年${arr[1]}岁,来自于${arr[2]}"
echo "直接打印所有内容:${arr[@]}"

1229382-20190728204624698-2056025751.png

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

#!/bin/sh
arr=(1 2 3 4 5)
# 获取数组元素的个数,这里加上了[@]
echo "${#arr[@]}"  # 或者${#arr[*]}也是一样的

# 如果没有[@]
echo "${#arr}"
# 直接输出数组
echo "${arr}"

1229382-20190728204630924-1196987520.png



shell运算符


算数运算符

bash不支持原生的数学运算,但是我们可以通过expr来实现
#!/bin/bash

val=`expr 2 + 2`  # 表示计算2+2的值,注意+两边要有空格,而且这里是反引号,expr 表示计算后面的值
echo "${val}"

a=10
b=20
val=`expr ${a} + ${b}`
echo "${val}"

# 如果+两边没有空格
val=`expr 2+2`
echo "${val}"

val=`expr ${a}+${b}`
echo "${val}"

1229382-20190728204645256-2065330260.png

#!/bin/bash
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 $a / $b`
echo "a/b=${val}"

val=`expr $a % $b`
echo "a%b=${val}"

val=`expr $a == $b`
echo "a==b=${val}"

val=`expr $a != $b`
echo "a!=b=${val}"

1229382-20190728204652393-1305616740.png


关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。假设a=10,b=20

  • -eq:检测两个数是否相等。[ $a -eq $b ] 返回 false。
  • -ne:检测两个数是否不相等。[ $a -ne $b ] 返回 true。
  • -gt:检测左边的数是否大于右边的数。[ $a -gt $b ] 返回 false。
  • -lt:检测左边的数是否小于右边的数。[ $a -lt $b ] 返回 true。
  • -ge:检测左边的数是否大于等于右边的数。[ $a -ge $b ] 返回 false。
  • -le:检测左边的数是否小于等于右边的数。[ $a -le $b ] 返回 true。

这个代码示例,在流程控制中会介绍


布尔运算符

假设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

  • &&:逻辑的 AND,[[ $a -lt 100 && $b -gt 100 ]] 返回 false
  • ||:逻辑的 OR,[[ $a -lt 100 || $b -gt 100 ]] 返回 true

字符串运算符

假定变量 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。
  • $:检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。

文件测试运算符

file="/root/sh/1.sh"

-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。

注意:凡是没有用代码举例的运算符,一般都是放在if else语句里面的,后面会说。这里想说的是,这些条件都是放在[]里面的,关键是[ ]前后要和代码有一个空格,这是必须的。也就是我们的条件是判断a和b是否相等,要这么写[ $a -eq $b ],不可以这么写,[$a -eq $b], 内容不能和[]两边挨着



shell echo命令

很早之前就介绍过了,这里再复习一遍

显示普通字符串

#!/bin/sh
echo "my name is mashiro"
echo my name is mashiro  # 这里的""可以省略

1229382-20190728204701961-1095310320.png

显示转义字符

#!/bin/bash
echo "\"my name is mashiro\""
echo \"my name is mashiro\"  # 同理""也可以省略

1229382-20190728204708840-658777251.png

显示变量

#!/bin/sh
read name  # read name 表示从命令行读取,然后将值赋值给name

echo "my name is ${name}"

1229382-20190728204717109-1960294238.png

同理read也可以接收多个变量

#!/bin/sh
read name age gender
echo "$name $age $gender"

1229382-20190728204731712-1483123185.png



shell printf命令

printf 命令模仿 C 程序库(library)里的 printf() 程序。

printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。
#!/bin/bash
echo "hello world"
printf "hello world\n"

1229382-20190728204739325-887864316.png

#!/bin/sh
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

1229382-20190728204746191-1636650435.png



shell 流程控制


if else

注意在shell里面,如果不需要else,那么就不要写。如果是其它编程语言的话,可以加上else不写逻辑,但是shell不行

if语法格式

if condition
then
    command1 
    command2
    ...
    commandN 
fi

也可以写成一行,但是要加上; if condition;then command;fi
末尾的fi就是if倒过来拼写,后面还会遇到类似的。

if else 语法格式

if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi


if else-if else 语法格式

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi
#!/bin/sh

read age gender

# 注意这里可不要写成 $age >= 18,这是不行的。
# 对于是否相等,则既可以用$age == 18和$age -eq 18
# 而且字符串要用=来判断,注意是=,不是==
if [ $age -ge 18 -a $gender = "f" ]
then
  echo "perhaps we can make a deal"
else
  echo "不约"
fi

1229382-20190728204756602-281676642.png

#!/bin/sh

read age gender

if [ $age -ge 18 -o $gender = "f" ]
then
  echo "perhaps we can make a deal"
else
  echo "不约"
fi

1229382-20190728204804716-906690269.png

#!/bin/bash

a=10
b=10

if [ $a == $b ]
then
  echo "a和b是相等的"
fi

if [ $a -eq $b ]
then
  echo "a和b是相等的"
fi

1229382-20190728204812006-1215637331.png

#!/bin/bash

read a b 

if [ $a -gt $b ]
then
  echo "a是大于b的"
elif [ $a -lt $b ]
then 
  echo "a是小于b的"
else
  echo "a是等于b的"
fi

1229382-20190728204821126-1828589236.png


for循环

for循环一般格式为:

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
或者
for var in item1 item2 ... itemN;do
    command1
    command2
    ...
    commandN
done

写成一行:for var in item1 item2 ... itemN; do command1; command2…; done;

in列表是可选的,如果不用它,for循环使用命令行的位置参数。
#!/bin/bash

for v in 1 2 3 4 5
do
  echo "val=${v}"
done

arr=("a" "b" "c" "d")
for v in ${arr[@]}  # 遍历数组,记得加上[@],否则只打印第一个元素
do
  echo "val=${v}"
done

1229382-20190728204828464-1307215783.png


while 语句

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while condition
do
    command
done
#!/bin/sh
num=1
while [ $num -lt 5 ]  # 当num小于5的时候
do
    echo "num=$num"
    let "num++"  # let可以执行表达式,让变量计算不需要加上$
done

1229382-20190728204836492-463544620.png


break和contiune

break结束当前循环,continue继续下一层循环

#!/bin/bash

echo "输入一个可以执行的文件"
while read file
do
  if [ -x ${file} ]
  then
    echo "文件为${file},这是一个可以执行的文件,循环结束"
    break
  else
    echo "文件为${file},这不是一个可以执行的文件,请重新输入"
    continue
  fi
done

1229382-20190728204843070-707451859.png


until 循环

until 循环执行一系列命令直至条件为 true 时停止。

until 循环与 while 循环在处理方式上刚好相反。

一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

until condition
do
    command
done
#!/bin/bash
a=1
until [ ! $a -le 10 ]  # !表示取反
do
  echo "a=${a}"
  let "a++"
  a=`expr ${a} + 1`  # 除了let "a++"还可这么写
done

1229382-20190728204850549-1176354387.png


case

Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:
case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
#!/bin/bash

echo "请输入abcde五个字符中的一个"
read alpha

case ${alpha} in
  a) echo "你选择了a"
  ;;
  b) echo "你选择了b"
  ;;
  c) echo "你选择了c"
  ;;
  d) echo "你选择了d"
  ;;
  e) echo "你选择了e"
  ;;
  *) echo "不在abcde当中"
  ;;
esac

1229382-20190728204911886-366473494.png

shell的case语句设计的很有个性



shell 函数


定义函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
shell中函数的定义格式如下:

funcName(){
    函数体
}
#!/bin/bash

mashiro(){
  echo "i'm mashiro"
}

echo "调用函数啦"
mashiro  # 调用函数不用加括号
echo "函数调用完毕"

1229382-20190728204919242-2050887158.png


函数的返回值

#!/bin/bash
add(){
  echo "输入两个数字:"
  read a b
  return `expr $a + $b`
}
add
num=$?  # 函数的返回值,在调用完函数之和,通过$?获取。并且要马上获取,如果获取之前插入了别的命令,就获取不到了,只能获取到0。并且函数只能返回整型
echo "输入的两个数字之和为:${num}" 
if [ $num -gt 10 ]
then
  echo "两个数字之和大于10"
else
  echo "两个数字之和小于等于10"
fi

1229382-20190728204926726-701047472.png


函数参数

shell中怎么给传递参数呢?还记得之前的向shell脚本传递参数的$1 $2...$n吗?
#!/bin/sh

func(){
  echo "函数的第一个参数是:$1"
  echo "函数的第二个参数是:$2"
  echo "函数的第三个参数是:$3"
  echo "函数的第四个参数是:$4"
}

func 1 2 3 4   # 直接在函数名后面传递参数即可,注意如果函数的参数超过了十个,那么从第十个开始要通过${10}这样的方式获取,要加上{}
# 函数参数的获取是从1开始的,第一个参数就是$1

1229382-20190728204933915-239292940.png



shell 引用文件

和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
引用方式,通过.来引用,直接. xxx.sh文件路径 即可,注意.和shell脚本之间要有空格

比如我们写了一个fuck.sh,那么在相同目录下创建的test.sh要想引用的话,就可以通过. ./fuck.sh来引用。第一个.表示引用,第二个.则是表示引用的文件的所在目录

/root/fuck.sh

#!/bin/bash
url="http://www.bilibili.com"

/root/sh/test.sh

#!/bin/bash
. ../fuck.sh
echo "${url}"

1229382-20190728204940684-552834915.png

转载于:https://www.cnblogs.com/traditional/p/11260842.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CWG2017/article/details/101169323

智能推荐

什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的区别及作用?_成员内部类和局部内部类的区别-程序员宅基地

文章浏览阅读3.4k次,点赞8次,收藏42次。一、什么是内部类?or 内部类的概念内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。public class TestA{ class TestB {}}二、 为什么需要内部类?or 内部类有什么作用?1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。2、内部类可以对同一个包中的其他类隐藏起来。3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。三、 内部类的分类成员内部_成员内部类和局部内部类的区别

分布式系统_分布式系统运维工具-程序员宅基地

文章浏览阅读118次。分布式系统要求拆分分布式思想的实质搭配要求分布式系统要求按照某些特定的规则将项目进行拆分。如果将一个项目的所有模板功能都写到一起,当某个模块出现问题时将直接导致整个服务器出现问题。拆分按照业务拆分为不同的服务器,有效的降低系统架构的耦合性在业务拆分的基础上可按照代码层级进行拆分(view、controller、service、pojo)分布式思想的实质分布式思想的实质是为了系统的..._分布式系统运维工具

用Exce分析l数据极简入门_exce l趋势分析数据量-程序员宅基地

文章浏览阅读174次。1.数据源准备2.数据处理step1:数据表处理应用函数:①VLOOKUP函数; ② CONCATENATE函数终表:step2:数据透视表统计分析(1) 透视表汇总不同渠道用户数, 金额(2)透视表汇总不同日期购买用户数,金额(3)透视表汇总不同用户购买订单数,金额step3:讲第二步结果可视化, 比如, 柱形图(1)不同渠道用户数, 金额(2)不同日期..._exce l趋势分析数据量

宁盾堡垒机双因素认证方案_horizon宁盾双因素配置-程序员宅基地

文章浏览阅读3.3k次。堡垒机可以为企业实现服务器、网络设备、数据库、安全设备等的集中管控和安全可靠运行,帮助IT运维人员提高工作效率。通俗来说,就是用来控制哪些人可以登录哪些资产(事先防范和事中控制),以及录像记录登录资产后做了什么事情(事后溯源)。由于堡垒机内部保存着企业所有的设备资产和权限关系,是企业内部信息安全的重要一环。但目前出现的以下问题产生了很大安全隐患:密码设置过于简单,容易被暴力破解;为方便记忆,设置统一的密码,一旦单点被破,极易引发全面危机。在单一的静态密码验证机制下,登录密码是堡垒机安全的唯一_horizon宁盾双因素配置

谷歌浏览器安装(Win、Linux、离线安装)_chrome linux debian离线安装依赖-程序员宅基地

文章浏览阅读7.7k次,点赞4次,收藏16次。Chrome作为一款挺不错的浏览器,其有着诸多的优良特性,并且支持跨平台。其支持(Windows、Linux、Mac OS X、BSD、Android),在绝大多数情况下,其的安装都很简单,但有时会由于网络原因,无法安装,所以在这里总结下Chrome的安装。Windows下的安装:在线安装:离线安装:Linux下的安装:在线安装:离线安装:..._chrome linux debian离线安装依赖

烤仔TVの尚书房 | 逃离北上广?不如押宝越南“北上广”-程序员宅基地

文章浏览阅读153次。中国发达城市榜单每天都在刷新,但无非是北上广轮流坐庄。北京拥有最顶尖的文化资源,上海是“摩登”的国际化大都市,广州是活力四射的千年商都。GDP和发展潜力是衡量城市的数字指...

随便推点

java spark的使用和配置_使用java调用spark注册进去的程序-程序员宅基地

文章浏览阅读3.3k次。前言spark在java使用比较少,多是scala的用法,我这里介绍一下我在项目中使用的代码配置详细算法的使用请点击我主页列表查看版本jar版本说明spark3.0.1scala2.12这个版本注意和spark版本对应,只是为了引jar包springboot版本2.3.2.RELEASEmaven<!-- spark --> <dependency> <gro_使用java调用spark注册进去的程序

汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用_uds协议栈 源代码-程序员宅基地

文章浏览阅读4.8k次。汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用,代码精简高效,大厂出品有量产保证。:139800617636213023darcy169_uds协议栈 源代码

AUTOSAR基础篇之OS(下)_autosar 定义了 5 种多核支持类型-程序员宅基地

文章浏览阅读4.6k次,点赞20次,收藏148次。AUTOSAR基础篇之OS(下)前言首先,请问大家几个小小的问题,你清楚:你知道多核OS在什么场景下使用吗?多核系统OS又是如何协同启动或者关闭的呢?AUTOSAR OS存在哪些功能安全等方面的要求呢?多核OS之间的启动关闭与单核相比又存在哪些异同呢?。。。。。。今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCXrdI0k-1636287756923)(https://gite_autosar 定义了 5 种多核支持类型

VS报错无法打开自己写的头文件_vs2013打不开自己定义的头文件-程序员宅基地

文章浏览阅读2.2k次,点赞6次,收藏14次。原因:自己写的头文件没有被加入到方案的包含目录中去,无法被检索到,也就无法打开。将自己写的头文件都放入header files。然后在VS界面上,右键方案名,点击属性。将自己头文件夹的目录添加进去。_vs2013打不开自己定义的头文件

【Redis】Redis基础命令集详解_redis命令-程序员宅基地

文章浏览阅读3.3w次,点赞80次,收藏342次。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。当数据量很大时,count 的数量的指定可能会不起作用,Redis 会自动调整每次的遍历数目。_redis命令

URP渲染管线简介-程序员宅基地

文章浏览阅读449次,点赞3次,收藏3次。URP的设计目标是在保持高性能的同时,提供更多的渲染功能和自定义选项。与普通项目相比,会多出Presets文件夹,里面包含着一些设置,包括本色,声音,法线,贴图等设置。全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,主光源和附加光源在一次Pass中可以一起着色。URP:全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,一次Pass可以计算多个光源。可编程渲染管线:渲染策略是可以供程序员定制的,可以定制的有:光照计算和光源,深度测试,摄像机光照烘焙,后期处理策略等等。_urp渲染管线

推荐文章

热门文章

相关标签