shell

shell脚本编程
1、环境变量:
生效方法:

        source filename
        . filename

2、常用的环境变量:

    /etc/profile
    /etc/profile.d/.sh
    /etc/bashrc
    ~/.bashrc
    ~/.bash_profile

放在/etc/的环境变量对所有用户生效
放在用户家目录下的环境变量仅对当前用户生效

3、环境变量的加载过程
需要输入用户名和密码的情况下:

/etc/profile->{/etc/profile.d/*.sh->/etc/profile.d/lang.sh->/etc/sysconfig/i18n,
~./bash_profile->~./bashrc->/etc/bashrc/->命令提示符}

在/etc/bashrc中定义了PS1,如果在流程中的某个配置文件被删除,/etc/bashrc就会调用失败,引起命令行显示不正常。
通过su切换,不需要账号密码的登陆:

        /etc/bashrc/->/etc/profile.d/*.sh->lang.sh->/etc/sysconfig/i18n

i18n文件定义了操作系统的语言,而lang.sh又调用了i8n。

4、/etc/profile的作用:

定义用户登录时的:
        USER变量
        LOGNAME变量
        PATH变量
        HOSTNAME变量
        HISTSIZE变量
        umask
        调用/etc/profile.d/*.sh文件

5、UMASK
文件的默认权限是666 “文件默认不给执行权限,如果要执行,需要额外赋予”
目录的默认权限是777
所以当umask为0022时,
创建一个文件所具有的权限是:
rw-rw-rw- - —-w–w– = rw-r–r– 644
创建一个目录所具有的权限是755
6、locale
查看系统的语言
查看语言调用可以通过/etc/profile.d/lang.sh查看
7、在退出登录时,会调用用户家目录中的bash_logout.sh文件,默认该文件为空,如果想在用户退出时执行什么操作,可以在此处添加,如:history -c清空历史命令
8、登陆警告信息
本地终端警告信息:
/etc/issue
远程终端警告信息
/etc/issue.net
但是,在该文件下,任何转义字符都无效,若想使其生效,需要修改远程登陆程序的配置:
/etc/ssh/sshd_conifg,加入”Banner /etc/issue.net”,然后重启sshd服务,使其生效。

**修改/etc/motd对本地和远程均能生效**

8、vim编辑器
语法高亮:syntax on
自动缩进:set autoindent
set cindent
9、shell编程的环境变量
环境变量一般是指用export内置命令导出的变量
设置历史命令的条数,在bashrc中有定义,HOSTSIZE,由于这些历史命令保存在本地磁盘上,所以,可以将默认条数。

设置环境变量:
    变量名一般要大写 
    如果要设置环境变量,那么就要在给变量赋值后或者在设定变量时用export命令或这declare -x 来设定

    export 变量名=value
    变量名=value;export 变量名
    declare -x 变量名=value

    使环境变量永久生效的方法使写入bashrc配置中。

    如果想要登陆后初始化或这显示加载内容,可以将文件放在/etc/profile.d/下,此文件下的.sh 文件在每次正常登录后都会重新执行一遍。
查看环境变量的方法:
    env set     显示默认的环境变量

取消环境变量:
    unset 消除本地和环境变量
    unset name

10、变量

把一个命令的结果作为变量赋值的方法:
        变量名=·ls·    不推荐反引号
        变量名=$(ls)	把命令用$()括起来,推荐

example:

按天打包网站的站点目录程序,生成不同的文件名:
    CMD=$(date +%F)
    tar cf etc_$CMD.tar  /etc
    此时,打包出来的结尾为日期的文件
    在引用变量时一定要注意{}的范围。
    shell脚本中的特殊位置参数变量:
        $0:获取当前执行的Shell脚本的文件名,如果执行脚本包含了路径,那么就包含脚本路径
        $n:获取当前执行的shell脚本的第n个参数值。n=1..9
        $#:获取当前执行的Shell脚本后边接的参数的总个数。
        $*:获取当前shell脚本所有传递的参数。如果使用“$*”,那么他将所有参数视为单个字符串相当于"$1 $2"作为一个字符串输出
    分离出文件名和路径名:
        [root@localhost ~]# sh /root/test.sh 
        /root
        test.sh
        [root@localhost ~]# cat test.sh 
        #########################################################################
        # File Name: test.sh
        # author: Ginkgo
        # mail: 907632998@qq.com
        # Created Time: Sun 11 Jun 2017 01:33:22 PM EDT
        #########################################################################
        #!/bin/bash
        dirname $0
        basename $0

11、shell进程中的特殊状态变量
?:0 :Shell使 ?查看软件是否安装成功

    $?的用法:
        1)判断命令,脚本,函数或程序是否执行成功
        2)若在脚本中调用exit数字,则会把这个数字赋值给$?
        3)如果在函数中调用了return 数字,则会把这个数字赋值给$?

                                                -a file exists. 
                                                -b file exists and is a block special file. 
                                                -c file exists and is a character special file. 
                                                -d file exists and is a directory. 
                                                -e file exists (just the same as -a). 
                                                -f file exists and is a regular file. 
                                                -g file exists and has its setgid(2) bit set. 
                                                -G file exists and has the same group ID as this process. 
                                                -k file exists and has its sticky bit set. 
                                                -L file exists and is a symbolic link. 
                                                -n string length is not zero. 
                                                -o Named option is set on. 
                                                -O file exists and is owned by the user ID of this process. 
                                                -p file exists and is a first in, first out (FIFO) special file or named pipe. 
                                                -r file exists and is readable by the current process. 
                                                -s file exists and has a size greater than zero. 
                                                -S file exists and is a socket. 
                                                -t file descriptor number fildes is open and associated with a 
                                                terminal device. 
                                                -u file exists and has its setuid(2) bit set. 
                                                -w file exists and is writable by the current process. 
                                                -x file exists and is executable by the current process. 
                                                -z string length is zero. 

example:实现系统中多次执行某一个脚本后的进程只有一个。
有时执行定时任务的脚本频率较快,并不知道上一个脚本是否真的执行完成,但是业务要求同一时刻内只有一个同样的脚本运行,可以用$$。
cat pid.sh

                    #!/bin/bash
                    pidpath=/tmp/a.pid
                    if [ -a "$pidpath" ]
                        then
                            kill $(cat $pidpath) >/dev/null 2>&1
                            rm -f $pidpath
                    fi
                    echo $$ >$pidpath
                    sleep 300

12、bash shell内置变量命令
1)echo 在屏幕上输出信息
参数:
-n 不换行输出内容
-e 解析转义字符
\n 换行
\r 回车
\t tab
\v 纵向制表位

2)exec 在不创建新的子进程的前提下,转去执行制定的命令。
example:
            [root@localhost ~]# sh exec.sh  
            1
            2
            3
            4
            5
            ok
            [root@localhost ~]# cat exec.sh 
            #########################################################################
            # File Name: exec.sh
            # author: Ginkgo
            # mail: 907632998@qq.com
            # Created Time: Sun 11 Jun 2017 02:42:09 PM EDT
            #########################################################################
            #!/bin/bash
            exec </tmp/tmp.log
            while read line
            do
                echo $line
            done
            echo ok
3)read read变量表名

13、shell变量子串parameter为变量。

    ${parameter}	返回$parameter的内容
    ${#parameter}      返回字符串的长度,按字符,适用于特殊变量
    ${parameter:offset} 从offset处向后提取字符串    offset位置。
    ${parameter:offset:length} 从offset处向后提取length长度的字符串
    ${parameter#(%)word}   从开头(结尾)开始删除最短匹配的word子串。支持正则表达
    ${parameter##(%%)word} 从开头(结尾)删除最长匹配的word子串
    ${parameter/pattern/string}    用string替换第一个匹配的pattern
    ${parameter//pattern/string} 用string替换所有的pattern

进行批处理:
假设有一批文件,文件有相同的属性,比如都是以.jpg为后缀,可以同一改名。
执行:

for f in `ls *fin*.jpg`;do mv $f `echo ${f//_finished/}`;done
        [root@localhost test]# cat test
        stu_102999_1_finished.jpg 
        stu_102999_2_finished.jpg 
        stu_102999_3_finished.jpg 
        stu_102999_4_finished.jpg 
        stu_102999_5_finished.jpg 
        [root@localhost test]# cat test.sh 
        #!/bin/bash
        for f in `cat ./test` 
        do
            echo $f
            touch $f
            mv $f `echo ${f//_finished/}`
        done
        [root@localhost test]# ls
        stu_102999_1.jpg  stu_102999_2.jpg  stu_102999_3.jpg  stu_102999_4.jpg  stu_102999_5.jpg  test  test.sh

            [root@localhost ~]# sh p.sh 
            Please input first number: 1
            1
            Please input operators: -
            Please input the second number: 1
            1-1 = 0
            [root@localhost ~]# ls
            p.sh
            [root@localhost ~]# cat p.sh
            #!/bin/bash
            read -p "Please input first number: " firstnum
            echo $firstnum
            read -p "Please input operators: " operations
            if [[ "$operations" != "+" ]] && [[ "$operations" != "-" ]] && [[ "$operations" != "*" ]] && [[ "$operations" != "/" ]]
            then
                echo "Please 'echo' '+'or'-'or'*'or'/' "
            else
                read -p "Please input the second number: " secondnum

            fi

            echo "${firstnum}${operations}${secondnum}" = "$((${firstnum}${operations}${secondnum}))"
let 运算命令的用法:
    let运算命令的格式为:let 赋值表达式
    let赋值表达式的功能等同于"(())"
    let i=i+8
expr 用于计算:
    expr 2 + 2
    expr 2 \* 2
在使用expr时,运算符用于计算数字左右至少有一个空格
                            *号要进行转义
                            在shell中进行运算要使用反引号
                判断一个输入是否为数字:
                    [root@localhost ~]# cat q.sh
                #!/bin/bash
                read -p "Please inter a id: " id
                expr $id + 1 >/dev/null
                if [ 0 = $? ]
                then
                    echo "THe id is num"
                    else
                    echo "error"
                fi
在输入的一句话中打印出字数大于6的。
            [root@localhost ~]# cat r.sh 

            #!/bin/bash
            read -p "Please input a word: " word
            echo $word
            for i in $word
            do 
                if [ ${#i} -gt 6 ];then
                    echo $i
                fi
            done
            [root@localhost ~]# sh r.sh 
            Please input a word: hello my bestfirends              
            hello my bestfirends
            bestfirends

grep :
    grep :
        -c 只输出匹配行的计数
        -h 查询多文件时不显示文件名
        -I  查询多文件时只输出包含匹配字符的文件
        -n 显示匹配行及行号
        -v 显示不包含匹配文本的所有行
    正则:
        \ 转义
        ^ 匹配正则表达式开始的行
        $ 匹配正则表达式结束的行
        \< 从匹配正则表达式的行开始
        \> 到匹配正则表达式结束的行结束
        [ ] 单个字符(其中的字符串都作为单个字符存在)
        [-] 范围:如a-z 
        .  所有的单个字符
        * 有字符,长度可以为0
        a{2}含有两个a的行
        a{2,}含有两个a以上的行
        a{2,4}含有2到4个a的行

    实例:
        grep 'w\(es\).*\1' aa
        在aa文件中,如果west被匹配,那么es就被写入内存中,并标记为1,然后搜索任意个字符,这些字符后边紧跟着另一个es(\1),找到就显示该行。
        grep "r\(oo\)t\1" test 
        rootoo
        grep 'test' d*
        显示所有以d开头的文件中包含的行
        grep '[a-z]\{5\}' aa
        显示所有包含每个字符串至少有5个连续小写字符串的行

        grep "^[^200]" a
        在a文件中查找不一2 0 0 开头的行
        [^ ]除了
        [root@localhost ~]# cat test 
        200
        2342342200
        332002304
        [root@localhost ~]# grep "^[^200]" test 
        332002304

    ``的作用:将里边命令的执行的输出返回给前边的变量
    ``中的东西并不会输出出来
    方便和别的内容相结合。

echo -e 在最后会自动换行,可以解析转义字符
echo -n 输出之后不换行
然后使用read 命令读取
        =read -p "Please input d word :" word



cut 
    -d  以什么做分割
    -f 拿出第几列
awk
    -F 以什么分割
    '{print $1 '==>' $3}'

    awk的默认分隔符为空格,不需要表示
    awk中的常量NR表示第几行
    df |awk '{if(NR==3) {print $1}}'
    取出第三行的第一列 $0代表所有 
    df |awk '{if(NR==2){print}}'
    打印第二行的所有 
    awk的转整形:int()将非整形元素变为整形
    df |awk '{if(NR==3){print $1 }'如果$1为40%,可以使用
    df |awk '{if(NR==3){print int($1) }'输出为40

    输出文件的行:
        df |awk 'END {print NR}'
    输出文件的列:
        df |awk 'END {print NF}'
    awk里边的匹配:~/   /
                    不匹配:!~/  /

    cat file |awk '$0 !~/192.169.244.1/ {print $0}'
    取出file中不配配/  /的整行

awk:

1、调用awk
    有三种方式调用awk,
        第一种是命令行方式,如:
        awk [-F field-separator] 'commands' inputfiles
        commands是真正的awk命令
        第二种是将所有的awk命令插入一个文件,并使awk程序可以执行,然后使用awk命令执行,以便通过键入脚本名称来调用他们
    第三种是将所有的awk命令插入一个单独的文件然后调用
    awk -f awk-script-file inputfiles
    -f 指明在文件awk-scriipt-file中的脚本,inputfiles是使用awk进行浏览的文件

2、awk脚本
任何awk语句都由模式和动作组成,在一个awk脚本中可能有许多语句,模式部分决定动作语句何时触发及触发事件,处理即对数据进行操作,如果省略模式部分,动作将时刻保持执行状态。

    模式可以是任何条件语句或复合语句或正则表达式,模式包括两个特殊字段BEGIN和END,使用BEGIN语句设置计数和打印头,BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明,awk总是匹配或打印行数。
    awk -F : 'BEGIN{print "start\tend\t" } {print $1"\t"$3} END{print "endoffile" }' passwd |head -n 5
    **end结果在所有文本按行执行完成之后的结尾,不因head语句出现问题。
    start   end 
        root    0
        bin 1
        daemon  2
        adm 3

        实际动作在大括号内指明。

3、域和记录
        awk执行时,其浏览域标记为$1,$2....,这种方法叫做域标识,,$0表示所有域。

4、规则:
        确保整个awk命令用单引号括起来
        确保命令内引号成对出现
        确保用花括号括起动作语句,用圆括号括起条件语句。
5、awk中正则表达式
        awk中的正则表达式用斜线括起来,如/awk/
        元字符: \ ^ $ . [] | () * + ?
        其中:使用+匹配一个或多个字符
                    ?匹配出现的频率例如使用/XY?Z/匹配XYZ 或 YZ
        条件操作符:
            < > >= =<  ~匹配   !~不匹配
        awk -F : '{if($3 !~/0/) print $3}' passwd  |head

6、awk的内置变量
        awk有许多内置变量用来设置环境信息。这些变量可以被改变。
        ARGC 命令行参数个数

        ARGV 命令行参数排列

        ENVIRON 支持队列中系统环境变量的使用

        FILENAME awk浏览的文件名

        FNR 浏览文件的记录数

        FS 设置输入域分隔符,等价于命令行- F选项

        NF 浏览记录的域个数 

        NR 已读的记录数

        OFS 输出域分隔符  缺省为空格

        ORS 输出记录分隔符  缺省为新行\n

        RS 控制记录分隔符      缺省为新行

        ARGC支持命令行中传入awk脚本的参数个数。

        ARGV是ARGC的参数排列数组,其中每一元素表示为ARGV[n],n为期望访问的命令行参数。
# cat test |head -n 5
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    [root@localhost mnt]# awk '{print NR,NF}' test 
    1 1
    2 1
    3 1
    4 1
    5 1
awk获得外部变量:
    1、获得普通外部变量:
        test ="hello,world"

    # echo | awk -v test="$test" 'BEGIN{print test}'
    helloworld
    #  echo | awk -v test="$test" '{print test}'  
    helloworld
格式:
    awk -v 变量名=变量值 [-v 变量2=值2] ‘BEGIN{action}’  使用-v选项可以使action在任何情况下获得变量值,但是要求变量在action之前

    2、获得环境变量

         调用awk内部变量ENVIRON,就可以获得环境变量,他是一个字典数组,环境变量名就是它的键值。

sed:
sed [-nefr] ‘[action]’
选项与参数:
-n 使用安静模式,在一般sed用法中,所有来自STDIN的数据一般都会列到屏幕上,如果加上-n,则只有sed特殊处理的哪一行或动作才会被列出来
-e :
直接在命令列模式上进行sed的动作编辑
-f :
直接将sed的动作写在一个文件内,-f filename则可以运行filename的sed动作
-r: sed的动作支持的是延伸性正则表示法的语法。
-i :直接修改读取的内容,而不是输出到终端。
动作说明:
[n1[n2]] function
n1,n2一般代表【进行动作的次数/范围】
function:
a:新增,a后边可以接字符串,而这些字符串会在新的一行出现在目前行的下一行
c:取代,c后边的字符串可以取代n1,n2之间的行
d:删除,d后边不加任何东西。
i:插入,i的后边可以接字符串,而这些字符串会在新的一行出现,当前行的上一行。
p:打印,将某个选择的数据打印,P通常和sed -n 一起使用
s:取代,直接进行取代动作,可以支持正则表达。

        # sed '2,5d' test |wc -l
            6
            [root@localhost mnt]# cat test |wc -l
            10
            #   sed '2,$d' test  |wc -l    删除2到最后一行。
            1
            # sed '2i dirinktea' test |head -n 5
            root:x:0:0:root:/root:/bin/bash
            dirinktea
            bin:x:1:1:bin:/bin:/sbin/nologin
            daemon:x:2:2:daemon:/sbin:/sbin/nologin
            adm:x:3:4:adm:/var/adm:/sbin/nologin

        以行为单位的新增删除:
            将/etc/passwd的内容列出并将第2~5行删除。
            # nl /etc/passwd | sed '2,5d'
            1 root:x:0:0:root:/root:/bin/bash
            6 sync:x:5:0:sync:/sbin:/bin/sync
            7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
            删除从第二行到最后一行
            # nl /etc/passwd |sed '2,$d'
        1   root:x:0:0:root:/root:/bin/bash
        在第二行后添加drink tea
        [root@localhost mnt]# nl /etc/passwd|sed '4,$d'|sed '3i drink tea '
     1  root:x:0:0:root:/root:/bin/bash
     2  bin:x:1:1:bin:/bin:/sbin/nologin
        drink tea 
     3  daemon:x:2:2:daemon:/sbin:/sbin/nologin


            如果要添加新行,必须要使用\来进行新行的添加。

             nl /etc/passwd|sed '4,$d'|sed '2a drink tea or \
            > drink bear '
                 1  root:x:0:0:root:/root:/bin/bash
                 2  bin:x:1:1:bin:/bin:/sbin/nologin
            drink tea or 
            drink bear 
                 3  daemon:x:2:2:daemon:/sbin:/sbin/nologin

    以行为单位的替换和显示:
    # nl /etc/passwd|sed '4,$d'|sed '2,3c helloword'
 1  root:x:0:0:root:/root:/bin/bash
    helloword
    搜索并显示:
        # nl /etc/passwd|sed '4,$d'|sed '/root/p'
 1  root:x:0:0:root:/root:/bin/bash
 1  root:x:0:0:root:/root:/bin/bash
 2  bin:x:1:1:bin:/bin:/sbin/nologin
 3  daemon:x:2:2:daemon:/sbin:/sbin/nologin

        不但输出匹配行,还会输出所有行
        使用-n 参数,可以只输出匹配行。
    匹配行的删除:
            nl /etc/passwd | sed  '/root/d'
            2  daemon:x:1:1:daemon:/usr/sbin:/bin/sh
            3  bin:x:2:2:bin:/bin:/bin/sh

        数据的搜寻并执行命令
    找到匹配模式eastern的行后,

    搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行:

     nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p}'
     1  root:x:0:0:root:/root:/bin/blueshell
    如果只替换/etc/passwd的第一个bash关键字为blueshell,就退出

    nl /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}'    
    1  root:x:0:0:root:/root:/bin/blueshell 

    最后的q是退出。

    # ifconfig |sed -n '/inet/p'|grep -v inet6|awk 'BEGIN{print "ipaddr\t\tmask"} {print $2 "\t" $4}'
ipaddr      mask
172.25.254.1    255.255.255.0
127.0.0.1   255.0.0.0

shell脚本中的条件测试:
语法:test <测试表达式> test和测试表达式之间至少有一个空格
[<测试表达式>] 通过条件测试表达式的方法 [ ] 边界和内容之间至少一个空格
[[<条件测试表达式>]] [ ]边界和空格之间至少一个空格
(()) 进行条件测试表达式的方法,一般用于if语句。不需要空格

    example:
            test -f file && echo true ||echo false
            [ -f /tmp/file ] && echo true || echo false 
            测试的参数可以使用

                                                -a file exists. 
                                                -b file exists and is a block special file. 
                                                -c file exists and is a character special file. 
                                                -d file exists and is a directory. 
                                                -e file exists (just the same as -a). 
                                                -f file exists and is a regular file. 
                                                -g file exists and has its setgid(2) bit set. 
                                                -G file exists and has the same group ID as this process. 
                                                -k file exists and has its sticky bit set. 
                                                -L file exists and is a symbolic link. 
                                                -n string length is not zero. 
                                                -o Named option is set on. 
                                                -O file exists and is owned by the user ID of this process. 
                                                -p file exists and is a first in, first out (FIFO) special file or named pipe. 
                                                -r file exists and is readable by the current process. 
                                                -s file exists and has a size greater than zero. 
                                                -S file exists and is a socket. 
                                                -t file descriptor number fildes is open and associated with a 
                                                terminal device. 
                                                -u file exists and has its setuid(2) bit set. 
                                                -w file exists and is writable by the current process. 
                                                -x file exists and is executable by the current process. 
                                                -z string length is zero. 
字符串测试表达式
    -n "字符串"        字符串的长度不为0,为真
    -z "字符串"    字符串的长度为0,为真
    "串1" = "串2" 1=2 或1==2
    "串1"!= "串2" 1!=2 或1!==2
    "="两端要留有空格,不然会产生逻辑错误。
    字符串的比较一定要将字符串加入双引号再比较。

整数二元比较操作符:
    -eq "="         -gt ">"     -lt "<" -le  "<=" -ge   "》=" -ne "!="


    在[]和test中使用的操作符:
        -a == &&  -o == ||  ! == !

if 条件语句
1、单分支结构:
if <表达式>
then
指令
fi

if <表达式> ;then
指令
fi

case 条件语句:
case “变量” in
值1)
指令。。。
;;
值2)
指令….
;;
esac

while循环按行读取:
使用exec读入文件,然后按行处理:
exec < file
sum = 0
while read line
do
cmd
done

chattr 命令:
chattr命令适用于超级用户,change attrbute用于设置ext2,ext3文件的隐蔽属性,chattr[-RV] [+-][文件属性]文件或目录

-R:将目录下的所有子目录连同文件一起处理
-V:显示指令的执行过程
+:  开启某个文件或目录的该项属性
-:  关闭某个文件或目录的该项属性
=:  制定某个文件或目录的该项属性

a:  当设置为该属性时,该文件只能添加数据,不能删除
i;  当设置文件属性为i时,该文件不能被改名,删除和添加数据

chmod 只能改变文件的读写执行权限,更底层的属性则用chattr来实现。
如果用root账户仍然不能修改文件,就要考虑文件是否被锁定,使用lsattr来查看。
chattr不能用于/ ,/dev  /tmp /var目录。、
lsattr列出文件的隐藏属性
-a显示所有文件和目录
-d如果链接的是目录,则只列出目录的属性
-R递归,将子目录,文件都列出来。

find *** -exec cp {} /mnt/ \;
locate -u 更新locate库。
strings /lib64/libc.so.6 |grep GLIBC_

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值