shell脚本(上)

shell

  • Shell初探&注意事项
  • 标准输出&输入&错误
  • 三种运行方式
  • 变量与函数的定义与使用
  • 参数扩展
  • test与判断
  • 循环
  • Common Symol

Shell初探&注意事项

bash 复制代码
#!/bin/bash

: << !
    Shebang(Hashbang):一个由井号和叹号构成的字符序列#!出现在文本文件的第一行的前两个字符。
    操作系统的程序加载器会分析Shebang后的内容,将这些内容作为解释器指令。
    并调用该指令,并将载有Shebang的文件路径作为该解释器的参数。

    #!/usr/bin/python

    #!/usr/bin/env pyhon

    env:不同对操作系统,脚本解释器可能被安装于系统的不同的目录,设置到系统的PATH中。
    env可以在系统的PATH目录中查找。
    上述命令,使用在用户路径中找到的第一个Python版本。但是可以通过指定版本号:
    #!/usr/bin/env pythonX.x

    env也可以指定搜索目录:
    #!/usr/bin/env -S -P/usr/local/bin:/usr/bin:${PATH} python
    会在/usr/local/bin、/usr/bin、系统PATH搜索python。
    子进程:在当前的shell下,去打开另一个新shell。
    
    PS1提示符定义:提示符设置 [\u@\h \w \A #\#]\$
            1. \h 主机名缩写
            2. \u 用户账号名称
            3. \w 完整工作路径
            4. \A 24小时时间
            5. \# 第几个命令
            6. \$ 提示符,如果是root,提示符为#,否则是$
        HOME:代表用户主文件夹。
        SHELL:当前使用的是那个SHELL
        PATH:执行文件查找路径
        
    read [-pt] 变量 读取键盘变量
        -p:提示符
        -t:等待秒数
!

# echo "单行注释"

: << !
    多行注释方式一:
        echo "多行注释"
!

: << COMMENT
    多行注释方式二:
        echo "多行注释"
COMMENT

: '
    多行注释方式三:
        echo "多行注释"
'

if false; then
    多行注释方式四:
        echo "多行注释"
fi

((0)) && {
    多行注释方式五:
        echo "多行注释"
}

##这里默认会换行
#echo "输入网站名: "
##读取从键盘的输入
#read website
#echo "你输入的网站名是 $website"
特殊符号与使用
bash 复制代码
#!/bin/bash

: << !
如果路径中包含空格,则有三种不同的解决策略:

# 加 \ 转义
/mnt/c/Program\ Files/Walterlv/Foo

# 加双引号
"/mnt/c/Program Files/Walterlv/Foo"

# 加单引号
'/mnt/c/Program Files/Walterlv/Foo'
可以发现,两者都有的方案是加双引号。所以,如果希望你的命令脚本跨平台使用,则应该使用双引号包裹路径。

!
#转义空格。如果路径中包含空格,那么使用 \ 转义可以避免路径被分割成 Shell 的两个参数。


# grep "$KEY_WORD" --color=auto -- $FILE

grep weak --color=auto -- ../Common\ Symbol/test.m

grep weak --color=auto -- "../Common Symbol/test.m"

# 错误
# grep weak --color=auto -- "../Common\ Symbol/test.m"

# 错误
# grep weak --color=auto -- '../Common\ Symbol/test.m'
find_api.sh
bash 复制代码
#!/bin/bash

: << !
如果路径中包含空格,则有三种不同的解决策略:

# 加 \ 转义
/mnt/c/Program\ Files/Walterlv/Foo

# 加双引号
"/mnt/c/Program Files/Walterlv/Foo"

# 加单引号
'/mnt/c/Program Files/Walterlv/Foo'
可以发现,两者都有的方案是加双引号。所以,如果希望你的命令脚本跨平台使用,则应该使用双引号包裹路径。

!
#转义空格。如果路径中包含空格,那么使用 \ 转义可以避免路径被分割成 Shell 的两个参数。


# grep "$KEY_WORD" --color=auto -- $FILE

grep weak --color=auto -- ../Common\ Symbol/test.m

grep weak --color=auto -- "../Common Symbol/test.m"

# 错误
# grep weak --color=auto -- "../Common\ Symbol/test.m"

# 错误
# grep weak --color=auto -- '../Common\ Symbol/test.m'

标准输出&输入&错误

标准输出&输入&错误
bash 复制代码
#!/bin/bash

: 'COMMENT
    标准输入(stdin):代码为0,使用<或<<;
    标准输出(stdout):代码为1,使用>或>>;
    标准错误输出(stderr):代码为2,使用2>或2>>;
    1> 以覆盖的方式将正确的数据输出到指定到文件或设备;
    1>> 以累加到方法将正确到数据输出到指定到文件或者设备上;
    2> 以覆盖的方式将错误的数据输出到指定到文件或设备;
    2>> 以累加的方式将错误的数据输出到指定到文件或设备;
    < 标准输入;
    << 结束输入,后接一个结束输入符;
    2>/dev/null 将错误到数据丢弃,只显示正确到数据;
    2>&1 或者 &>将正确的数据和错误的数据写入同一个文件;
    1>&2 正确返回值传递给2输出通道 &2表示2输出通道;
    2>&1 错误返回值传递给1输出通道, 同样&1表示1输出通道;
    cmd;cmd 不考虑命令相关性,连续执行。
    当前一个命令执行成功会回传一个 $?=0的值。
    cmd1 && cmd2 如果第一个命令的$?为0,则执行第二个命令。
    cmd1 || cmd2 如果第一个命令的$?为0,则不执行第二个命令。否则执行第二个命令。
    |:管道仅能处理前面一个命令传来的正确信息,将正确信息作为stdin传给下一个命令。
        1、管道命令只处理前一个命令正确输出,不处理错误输出;

        2、管道命令右边命令,必须能够接收标准输入流命令才行;
        
        3、大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数。
        
    - :减号在一些命令中表示从标准输入(stdin)中获取内容
    xargs:是将标准输入转为命令行参数
COMMENT'


echo "LGCat" > Cat
#LGCat
cat Cat

echo "LGCat 帅" > Cat
#LGCat 帅
cat Cat

echo "LGCat 帅" >> Cat
#LGCat 帅
#LGCat 帅
cat Cat

#LGCat 帅
#LGCat 帅
cat < Cat
cat > Cat1237

cat > Cat1237 << "cat"

cat Cat | cat Cat1237 -
cat Cat | cat Cat1237

echo "Cat1237" | xargs cat -

echo "test.m" | grep weak
echo "test.m" | xargs grep weak
find_api.sh
bash 复制代码
#!/bin/bash

: << !
如果路径中包含空格,则有三种不同的解决策略:

# 加 \ 转义
/mnt/c/Program\ Files/Walterlv/Foo

# 加双引号
"/mnt/c/Program Files/Walterlv/Foo"

# 加单引号
'/mnt/c/Program Files/Walterlv/Foo'
可以发现,两者都有的方案是加双引号。所以,如果希望你的命令脚本跨平台使用,则应该使用双引号包裹路径。

!
#转义空格。如果路径中包含空格,那么使用 \ 转义可以避免路径被分割成 Shell 的两个参数。


# grep "$KEY_WORD" --color=auto -- $FILE

grep weak --color=auto -- ../Common\ Symbol/test.m

grep weak --color=auto -- "../Common Symbol/test.m"

# 错误
# grep weak --color=auto -- "../Common\ Symbol/test.m"

# 错误
# grep weak --color=auto -- '../Common\ Symbol/test.m'


nm -pa './Common Symbol/test' | grep weak --color=auto
xcode_run_cmd.sh
bash 复制代码
#!/bin/sh


RunCommand() {
  #判断全局字符串VERBOSE_SCRIPT_LOGGING是否为空。-n string判断字符串是否非空
  #[[是 bash 程序语言的关键字。用于判断
  if [[ -n "$VERBOSE_SCRIPT_LOGGING" ]]; then
    #作为一个字符串输出所有参数。使用时加引号"$*" 会将所有的参数作为一个整体,以"$1 $2 ... $n"的形式输出所有参数
      if [[ -n "$TTY" ]]; then
          echo "♦ $@" 1>$TTY
      else
          echo "♦ $*"
      fi
      echo "------------------------------------------------------------------------------" 1>$TTY
  fi
  #与$*相同。但是使用时加引号,并在引号中返回每个参数。"$@" 会将各个参数分开,以"$1" "$2" ... "$n" 的形式输出所有参数
  if [[ -n "$TTY" ]]; then
        eval "$@" &>$TTY
  else
      "$@"
  fi
  #显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
  return $?
}

EchoError() {
    #在shell脚本中,默认情况下,总是有三个文件处于打开状态,标准输入(键盘输入)、标准输出(输出到屏幕)、标准错误(也是输出到屏幕),它们分别对应的文件描述符是0,1,2
    # >  默认为标准输出重定向,与 1> 相同
    # 2>&1  意思是把 标准错误输出 重定向到 标准输出.
    # &>file  意思是把标准输出 和 标准错误输出 都重定向到文件file中
    # 1>&2 将标准输出重定向到标准错误输出。实际上就是打印所有参数已标准错误格式
    if [[ -n "$TTY" ]]; then
        echo "$@" 1>&2>$TTY
    else
        echo "$@" 1>&2
    fi
    
}

RunCMDToTTY() {
    if [[ ! -n "$TTY" ]]; then
        EchoError "=========================================="
        EchoError "ERROR: Not Config tty to output."
        exit -1
    fi
    # CMD = 运行到命令
    # TTY = 终端
    if [[ -n "$CMD" ]]; then
        RunCommand $CMD
    else
        EchoError "=========================================="
        EchoError "ERROR:Failed to run CMD. THE CMD must not null"
    fi
}


RunCMDToTTY

三种运行方式

bash 复制代码
#!/bin/bash
 
: 'COMMENT
    运行方式:
        1. sh:
            使用$ sh script.sh执行脚本时,当前shell是父进程,生成一个子shell进程,在子shell中执行脚本。
            脚本执行完毕,退出子shell,回到当前shell。$ ./script.sh与$ sh script.sh等效。也叫fork方式
        2. source:
            使用$ source script.sh方式,在当前上下文中执行脚本,不会生成新的进程。脚本执行完毕,回到当前shell。
            $ . script.sh与$ source script.sh等效。不需要有"执行权限"
        3. exec方式:
            使用exec ./scriptsh方式,会用command进程替换当前shell进程,并且保持PID不变。
            执行完毕,直接退出,不回到之前的shell环境。
    是否需要权限:
        1. sh/bash/zsh不需要有"执行权限"
        2. ./script.sh需要有"执行权限"
        3. source script.sh不需要有"执行权限"
        4. exec需要有"执行权限"
COMMENT'

变量与函数的定义与使用

变量的定义.sh
shell 复制代码
#!/bin/bash
 
: 'COMMENT
    1. Shell变量默认为字符串。shell不关心这个串是什么含义。
    2. Shell默认的数值运算是整数类型。所以若要进行数学运算,必须使用一些命令例如declare、expr、双括号等。
    3. Shell变量可分为两类:
      i. 局部变量:只在创建它们的shell中可用。在函数内定义,函数执行后就被删除。
      ii. 环境变量:可以在创建它们的shell及其派生出来的任意子进程中使用。在整个脚本执行期间,只要没有被删除就一直存在。
    3. 定义规则:变量名必须以字母或下划线字符开头。其余的字符可以是字母、数字(0~9)或下划线字符。任何其他的字符都标志着变量名的终止。
        小写敏感。
    4. 给变量赋值时,等号周围不能有任何空白符。
    5. 通常大写字符为系统默认变量。个人习惯。
    6. set:查看所有变量(含环境变量与自定义变量),以及设置shell变量的新变量值。
            -a:标示已修改的变量,以供输出至环境变量。
            -b:使被中止的后台程序立刻回报执行状态。
            -e:若指令传回值不等于0,则立即退出shell。
            -f:取消使用通配符。
            -h:自动记录函数的所在位置。
            -H Shell:可利用"!"加<指令编号>的方式来执行history中记录的指令。
            -k:指令所给的参数都会被视为此指令的环境变量。
            -l:记录for循环的变量名称。
            -m:使用监视模式。
            -n:只读取指令,而不实际执行。
            -p:启动优先顺序模式。
            -P:启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接。
            -t:执行完随后的指令,即退出shell。
            -u:当执行时使用到未定义过的变量,则显示错误信息。
            -v:显示shell所读取的输入值。
            -x:执行指令后,会先显示该指令及所下的参数。
    7. declare/typeset [-aixrp] 变量
        -a 将变量定义成数组
        -i 将变量定义成整数
        -x 将变量定义成环境变量
        -r 将变量定义成readonly
        -p:显示变量定义的方式和值
        +:取消变量属性,但是 +a 和 +r 无效,无法删除数组和只读属性,可以使用unset删除数组,但是 unset 不能删除只读变量。
    8. local关键字,用来在作用域内创建变量。出来作用域被销毁。
    9. export为shell变量或函数设置导出属性,成为环境变量。无法对未定义的函数添加导出属性。同时,重要的一点是,export的效力仅及于该次登陆操作。
        注销或者重新开一个窗口,export命令给出的环境变量都不存在了。
        -f:代表[变量名称]为函数名称。。
        -n:删除变量的导出属性。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
        -p:显示全部拥有导出属性的变量。
        -pf:显示全部拥有导出属性的函数。
        -nf:删除函数的导出属性。
        --:在它之后的选项无效。
    10. 通配符
        *:匹配任意字符串,包括空字符串,不包含对"/"字符的匹配。
        ?:匹配任意单个字符,不能匹配"/"字符。
        [abc]:匹配"a"或者"b"或者"c"字符。
        [^abc]:不匹配"a"或者"b"或者"c"字符。
        [a-z]:匹配26个英文小写字符中任意一个。

    用set命令可以查看所有的变量,unset var命令可以清除变量var,var相当于没有定义过。
    readonly var可以把var变为只读变量,定义之后不能对var进行任何更改。
    
COMMENT'

# 执行后显示7,注意空格。
# expr 3 + 4
# result=`expr 2 + 3`
# echo $result

# # 没有指定整型属性,输出为字符串'a+b'。
# declare a=3 b=4 c
# c=a+b
# # a+b
# echo ${c}
# declare -p a

# # 不过可以使用以下方式赋值。
# c=$((a+b))
# # 7
# echo ${c}

# 设置了整型属性就可以直接加了。
# declare -i a=3 b=4 c
# c=a+b
# # 7
# echo ${c}
# declare -p a

# declare -p VARIABLE

# # 定义函数内的全局变量
# function test() {
#   declare testA=3
#   VARIABLE="Value"
#   local testB=3
#   # 让我们查看它们的属性。
#   declare -p testA VARIABLE testB
# }
# # 执行函数。
# test
# #Value
# echo $testA $VARIABLE $testB

# export a b=3
# # 当然也可以先定义后增加导出属性
# export VARIABLE
# 删除变量的导出属性
# export -n a b
# function func_1(){ echo '123'; }
# # 为已定义函数增加导出属性
# export -f func_1
# # 删除函数的导出属性
# export -fn func_1

# set 11 22 33 44
# # 44
# echo $4
# # $4
# echo "\$$#"
# # 44 第一遍得到变量个数4,第二遍去第四个
# eval echo "\$$#"

# declare mylove='Cat' #定义新变量
# # env | grep mylove   mylove=Cat
# set -a mylove #设置为环境变量

# echo "./*.sh"
# echo "./*".sh
# MMM=`echo "./*.sh"`
# echo $MMM
# echo `echo "./*.sh"`
# echo ./*.sh
# set -- "./"*.sh
# echo "$1"


: 'COMMENT
    数组:
        var[1]="var1"
        var[2]=1
COMMENT'


ARRAY=(cat hank)

#2
echo ${#ARRAY[@]}
#cat hank
echo ${ARRAY[*]}

#cat
echo ${ARRAY[@]:0:1}


ARRAY_2=(${ARRAY[@]:0:1})

#1
echo ${#ARRAY_2[@]}

unset ARRAY[1]

#cat
echo ${ARRAY[*]}


#生成10 个随机数保存于数组中,并找出其最大值和最小值
declare -a rand
declare -i max=0
declare -i min=31234
for i in {0..9}; do
   rand[$i]=$RANDOM
   echo ${rand[$i]}
   [ ${rand[$i]} -gt $max ] && max=${rand[$i]}
   [ ${rand[$i]} -lt $min ] && min=${rand[$i]}
done
echo "Max: $max Min:$min"
函数.sh
shell 复制代码
#!/bin/bash

: 'COMMENT
    函数的声明形式:
       function 函数名 {
            函数体
       }
       function 函数名() {
            函数体
       }
       函数名() {
            函数体
       }
    1. 有funtion,可以不写(),没有function,必须写()。
    2. 函数名和"{"之间必须有空格。
    3. 不得声明形式参数。
    4. 必须在调用函数地方之前,声明函数
    5. 无法重载
    6. 后来的声明会覆盖之前的声明
    7. 没有返回值的函数,默认返回函数内最后一条指令的返回值。有返回值的函数,只能返回整数。
    8. 需要获得函数值,只能通过$?获得。通过=获得是空值。
    
    我们可以将shell中函数,看作是定义一个新的命令,因此各个输入参数直接用空格分隔。
    一次,命令里面获得参数方法可以通过:$0...$n得到。$0代表函数本身。
    $#:传入的参数的个数。
    $*:所有的位置参数(作为单个字符串)。
    $@:所有的位置参数(每个都作为独立的字符串)。
    $?:当前shell进程中,上一个命令的返回值,如果上一个命令成功执行则$?的值为0,否则为其他非零值。
    $$:当前shell进程的pid。
    $!:后台运行的最后一个进程的pid。
    $-:显示shell使用的当前选项。
    $_:之前命令的最后一个参数。
COMMENT'

# 无输出
# logic
# function DoWork {
#     local LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }

# DoWork() {
#     local LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }


# 无输出
# logic
# function DoWork {
#     local LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }
# echo $LG_CAT
# echo `DoWork`

# 无输出
# logic
# function DoWork {
#     LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }
# echo $LG_CAT
# echo `DoWork`

# logic
# 无输出
# function DoWork {
#     LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }
# echo `DoWork`
# echo $LG_CAT

# logic
# logic
# LG_Cat
# function DoWork {
#     LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }
# DoWork
# echo `DoWork`
# echo $LG_CAT

# logic
# 2
# logic
# 0
# function DoWork {
#     LG_CAT="LG_Cat"
#     echo "logic"
#     return 2
# }
# DoWork
# echo "$?"
# echo `DoWork`
# echo "$?"


# function DoWork {
#     echo "特殊变量:\n
#         \$#:$#\\n
#         \$0:$0\\n
#         \$1:$1\\n
#         \$2:$2\\n
#         \$*:$*\\n
#         \$@:$@\\n
#         \$$:$$\\n
#         \$-:$-\\n
#         \$_:$_
#          "
#     return 2
# }

# DoWork "Cat" "LGCat"
find_api.sh
bash 复制代码
#!/bin/bash
 
KEY_WORD=weak
FILE='./Common Symbol/test.m'

MACHO='./Common Symbol/test'

: << !
Linux 下,如果路径中包含空格,则有三种不同的解决策略:

# 加 \ 转义
/mnt/c/Program\ Files/Walterlv/Foo

# 加双引号
"/mnt/c/Program Files/Walterlv/Foo"

# 加单引号
'/mnt/c/Program Files/Walterlv/Foo'
可以发现,两者都有的方案是加双引号。所以,如果希望你的命令脚本跨平台使用,则应该使用双引号包裹路径。

!
#转义空格。如果路径中包含空格,那么使用 \ 转义可以避免路径被分割成 Shell 的两个参数。
#FILE=./Common\ Symbol/test.m



# grep "$KEY_WORD" --color=auto -- $FILE
grep "$KEY_WORD" --color=auto -- "$FILE"

nm -pa "$MACHO" | grep "$KEY_WORD" --color=auto

参数扩展

shell 复制代码
: 'COMMENT
    参数扩展:通过符号$获得参数中存储的值。
    1. 间接参数扩展
        i. ${parameter-string}:当parameter未设置则替换成string,不更改parameter值。否则,不做处理。
        ii. ${parameter=string}:当parameter未设置则替换成string,更改parameter值。否则,不做处理。
        iii. ${parameter?string}:parameter没有设置,则把string输出到标准错误中。否则,不做处理。
        iiii. ${parameter+string}:当parameter为空的时替换成string。否则,不做处理。
        ${!parameter},zsh不支持
    2. 冒号后面跟 等号,加号,减号,问号(⚠不能有空格):
        i. ${parameter:-string}:当parameter未设置或者为空则替换成string,不更改parameter值。
        ii. ${parameter:=string}:当parameter未设置或者为空则替换成string,更改parameter值。
        iii. ${parameter:?string}:若变量parameter不为空,则使用变量parameter的值。
             若为空,则把string输出到标准错误中,并从脚本中退出。
        iiii. ${parameter:+string}:当parameter不为空的时替换成string。若为空时则不替换或者说是替换空值。
    3. 子串扩展:${parameter:offset}和${parameter:offset:length}。
       从offset位置开始截取长度为length的子串,如果没有提供length,则是从offset开始到结尾。
        i. offset可以是负值,且必须与冒号有间隔或者用()包裹。开始位置是从字符串末尾开始算起,然后取长度为length的子串。
           例如,-1代表是从最后一个字符开始。
        ii. parameter是@,也就是所有的位置参数时,offset必须从1开始。
    4. 替换:${parameter/pattern/string}、${parameter//pattern/string}、${parameter/pattern}和${parameter//pattern}。
            大小写敏感。string为空时,则相当于将匹配的子串删除。 parameter之后如果是/,则只匹配遇到的第一个子串;
            parameter之后如果是//,则匹配所有的子串。
    5. 删除:${parameter#pattern}、${parameter##pattern}、${parameter%pattern}和${parameter%%pattern}。
        i. # 是去掉左边,% 是去掉右边。单一符号是最小匹配﹔两个符号是最大匹配。
    6. 参数长度:${#parameter}
COMMENT'

LONG_LONG_STRING="I am Cat!CAT!Cat!Cat"

# # Some string
# echo "${!VALUE}"

# #
# echo "${FOO-"Cat-"}"
# # Cat-
# echo "${FOO="Cat-"}"
# #
# echo "${FOO+"Cat-"}"
# # Cat-
# echo "${FOO?"Cat----"}"



# # Cat-
# echo "${FOO:-"Cat-"}"
# # Cat=
# echo "${FOO:="Cat="}"
# # Cat=
# echo "${FOO:?"Cat?"}"
# #Cat+
# echo "${FOO:+"Cat+"}"

# #Cat\
# echo "${LONG_STRING:5}"
# #Cat
# echo "${LONG_STRING:5:3}"
# #Cat
# echo "${LONG_STRING: -4:3}"
# #Cat
# echo "${LONG_STRING: -4:3}"
# #Cat
# echo "${LONG_STRING:(-4):3}"

# # I am Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING/cat}"
# # I am LGCat!CAT!LGCat!LGCat
# echo "${LONG_LONG_STRING//Cat/LGCat}"

# # am Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#* }"
# # am Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#? }"

# # at!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#*[Cc]}"

# if [[ -n $IS_ZSH ]]; then
#     # Cat!CAT!Cat!Cat
#     echo "${LONG_LONG_STRING#*(AT|m)}"
#     echo "-----${LONG_LONG_STRING#*(AT|m)}"
#     echo "-----${LONG_LONG_STRING#[A-z]**(AT|m)}"
#     # !Cat!Cat
#     echo "-----${LONG_LONG_STRING#*(AT|mm)}"
# fi

# # m Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#*[a-t]}"
# # m Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#*[a-t]}"
# # am Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING#*[^A-Z]}"

# echo `echo "./*.sh"`
# echo `echo "./"*.sh`

# # Cat!CAT!Cat!Cat
# echo "${LONG_LONG_STRING##* }"
# # at
# echo "${LONG_LONG_STRING##*[Cc]}"
# #
# echo "${LONG_LONG_STRING##*[a-t]}"

# # I am
# echo "${LONG_LONG_STRING% *}"
# # I
# echo "${LONG_LONG_STRING%% *}"

# # 20
# echo "${#LONG_LONG_STRING}"

# # i am cat!cat!cat!cat
# echo "$(echo "${LONG_LONG_STRING}" | tr "[:upper:]" "[:lower:]")"
# # I AM CAT!CAT!CAT!CAT
# echo "$(echo "${LONG_LONG_STRING}" | tr "[:lower:]" "[:upper:]")"

# if [[ -n $IS_ZSH ]]; then
#     # I AM CAT!CAT!CAT!CAT
#     echo "${LONG_LONG_STRING:u}"
#     # i am cat!cat!cat!cat
#     echo "${LONG_LONG_STRING:l}"
# fi
test与判断
bash 复制代码
#!/bin/bash

: 'COMMENT
    多分支语句判断
    除最后一个分支外(这个分支可以是普通分支,也可以是*)分支),其它的每个分支都必须以;;结尾,;;代表一个分支的结束,不写的话会有语法错误。
    最后一个分支可以写;;,也可以不写,因为无论如何,执行到 esac 都会结束整个 case in 语句。
    case $变量 in
    "第一个变量内容")
        程序
        ;;    #结束
    *)  # 用来托底,没有匹配到数据
        ;;
    esac
COMMENT'

: 'COMMENT
    一个条件判断:
        if [ condation ]; then
            成立
        else
            不成立
        fi

    多条件判断:
        if [ condation ]; then
            成立
        elif [ condation ]; then
            成立
        else
            不成立
        fi
COMMENT'


: 'COMMENT
    []:判断符号,两个等号和一个等号,效果类似。
    1. 中括号里面的每个组件都需要空格分隔。
    2. 中括号的变量,使用双引号
    3. 中括号的常量,使用单引号或双引号
COMMENT'

: 'COMMENT
    test命令测试:
    1. test n1 -eq n2:
        -eq:相等
        -ne:不等
        -gt:大于
        -lt:小于
        -ge:大于等于
        -le:小于等于
    2. 字符串判断
        -z string:判断string是否为0,为空,则为true。
        -n string:判断string是否非0,为空,则为false。
        string1 = string2:字符串是否相等,相等为true。
        string1 != string2:字符串是否不等,相等为false。
    3. 多重条件判断
        -a:两个条件同时成立,为true。
        -o:两个条件任何一个成立,为true。
        !:反向。
    4. 文件类型判断
        -e:文件名是否存在。
        -f:该文件名是否存在且是否为文件。
        -d:该名称是否存在且为目录。
        -L:该名称是否存在且是否为链接文件。
    5. 文件权限检测
        -r:是否存在是否有可读权限。
        -w:是否存在是否有可写权限。
        -x:是否存在是否有可执行权限。
        -s:是否存在且为非空白文件。
    6. 两文件比较
        -nt 文件1是否比文件2新。
        -ot 文件1是否比文件2旧。
        -ef 文件1和文件2是否为同一个文件。
COMMENT'


#
# if [ true ]; then
#     :
# fi

LG_CAT=Cat
function DoWork {
    return 2
}

DoWork

if [[ $? -ne 0 ]]; then
      
      echo "函数调用出错"
fi

if [[ "${LG_CAT}" == "Cat" ]]; then
    echo "${LG_CAT}"
fi

if [[ -e "./test与判断.sh" ]]; then
    echo "文件存在"
else
    echo "文件不存在"
fi


case $LG_CAT in
    "cat")
      echo "名字为cat"
      ;;
    "LGCat")
      echo "名字为LGCat"
      ;;
    *)
     echo "未找到名字"
     ;;
esac

循环.sh

bash 复制代码
#!/bin/bash

: 'COMMENT

    当条件成立,就进行循环:
        while [ condation ]  #判断条件
        do                   #循环开始
            程序
        done                 #循环结束
    当条件成立,就终止循环:
        until [ condation ]  #判断条件
        do                   #循环开始
            程序
        done                 #循环结束
    按照指定次数循环:
        for var in con1 con2 con3 ...
        do
            程序
        done
        
        for (( 初始值; 限制值; 执行步长 ))
        do
            程序
        done
COMMENT'

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done


for (( i = 1; i <= 5; i++ ))
do
    echo "i=$i"
done

# sh不支持
#for i in {1..100..2}
#do
#    echo $i
#done

COUNTER=0
while [ $COUNTER -lt 5 ]
do
    echo $COUNTER
    COUNTER=`expr $COUNTER + 1`
done

a=0
until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done

Common Symbol

scss 复制代码
#import <Foundation/Foundation.h>
// 符号表 -》NSlog -〉 导出符号 -》导入符号 -〉符号表 -》 nslog

void SomeNewFunction_weak_import(void) __attribute__((weak_import));

void SomeNewFunction_weak_import(void) {
    NSLog(@"SomeNewFunction_weak_import");
}

void SomeNewFunction_weak(void) __attribute__((weak));

void SomeNewFunction_weak(void) {
    NSLog(@"SomeNewFunction_weak");
}

void SomeNewFunction_weak_hidden(void) __attribute__((weak, visibility("hidden")));

void SomeNewFunction_weak_hidden(void) {
    NSLog(@"SomeNewFunction_weak");
}
// global_uninit_value = 0;
int global_uninit_value;
// 外部符号
int global_init_value = 10;


int global_init_value;

double default_y __attribute__((visibility("default"))) = 99 ;

//
void static_SomeNewFunction(void) __attribute__((visibility("hidden")));
void static_SomeNewFunction(void) {
    
}

// 外部
void SomeNewFunction_global(void) {
    NSLog(@"SomeNewFunction_weak");
}

double default_x;

static int static_init_value = 9;

static int static_init_value;

static int static_uninit_value;

static NSObject *object = nil;

static int static_uninit_value;

int main() {
    default_x = 11;
    static_uninit_value = 10;
    SomeNewFunction_global();
    int x;
    // 外部
    NSLog(@"LG_Cat-1");
    int a[4] = {1,2,3,4};
    NSLog(@"LG_Cat-2");
    int m = 10;
    NSLog(@"LG_Cat-3");
    return 0;
}
相关推荐
打小就很皮...2 小时前
简单实现Ajax基础应用
前端·javascript·ajax
wanhengidc3 小时前
服务器租用:高防CDN和加速CDN的区别
运维·服务器·前端
哆啦刘小洋3 小时前
HTML Day04
前端·html
再学一点就睡4 小时前
JSON Schema:禁锢的枷锁还是突破的阶梯?
前端·json
从零开始学习人工智能5 小时前
FastMCP:构建 MCP 服务器和客户端的高效 Python 框架
服务器·前端·网络
烛阴5 小时前
自动化测试、前后端mock数据量产利器:Chance.js深度教程
前端·javascript·后端
好好学习O(∩_∩)O5 小时前
QT6引入QMediaPlaylist类
前端·c++·ffmpeg·前端框架
敲代码的小吉米5 小时前
前端HTML contenteditable 属性使用指南
前端·html
testleaf6 小时前
React知识点梳理
前端·react.js·typescript
站在风口的猪11086 小时前
《前端面试题:HTML5、CSS3、ES6新特性》
前端·css3·html5