美文网首页
【技术整理】Shell脚本学习

【技术整理】Shell脚本学习

作者: 那年那月那猪在简书 | 来源:发表于2021-10-12 20:45 被阅读0次

    记录某个路径

    $ cd  $HOME$HOME
    $ alias pmd="$HOME/pmd-bin-6.6.0/bin/run.sh pmd"
    

    加脚本执行权限

    chmod +x ./generate_wordfile.sh

    $的参数意义

    $0 这个程式的执行名字
    $n 这个程式的第n个参数值,n=1..9
    $* 这个程式的所有参数,此选项参数可超过9个。
    $# 这个程式的参数个数
    $$ 这个程式的PID(脚本运行的当前进程ID号)
    $! 执行上一个背景指令的PID(后台运行的最后一个进程的进程ID号)
    $? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误·,其他任何值表明有错误)
    $- 显示shell使用的当前选项,与set命令功能相同
    $@ 跟$*类似,但是可以当作数组用
    
    ${var##*/} // 就是把变量var最后一个/以及左边的内容去掉
    ${var%/*} // 就是把变量var最后一个/以及右边的内容去掉
    
    ${var##*.} // 就是把变量var最后一个.以及左边的内容去掉
    ${var%.*} // 就是把变量var最后一个.以及右边的内容去掉
    
    ${var##*XYZ} // 就是把变量var最后一个XYZ以及左边的内容去掉
    ${var%XYZ*} // 就是把变量var最后一个XYZ以及右边的内容去掉
    
    $() // 小括号中执行方法
    ${} // 大括号中放置变量名
    ${n} // 大括号中放数字,表示传入的第n个参数,用于参数大于等于10个时使用
    

    数组

    // 得到数组元素总个数
    ${#filelist1[@]}
    

    if判断语句中的意思

    [ -a FILE ] 如果 FILE 存在则为真。

    [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。

    [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。

    [ -d FILE ] 如果 FILE 存在且是一个目录则为真。

    [ -e FILE ] 如果 FILE 存在则为真。

    [ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。

    [ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。

    [ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。

    [ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。

    [ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。

    [ -r FILE ] 如果 FILE 存在且是可读的则为真。

    [ -s FILE ] 如果 FILE 存在且大小不为0则为真。

    [ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。

    [ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。

    [ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。

    [ -x FILE ] 如果 FILE 存在且是可执行的则为真。

    [ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。

    [ -G FILE ] 如果 FILE 存在且属有效用户组则为真。

    [ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。

    [ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。

    [ -S FILE ] 如果 FILE 存在且是一个套接字则为真。

    [ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。

    [ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。

    [ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。

    [ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。

    [ -z STRING ] “STRING” 的长度为零则为真。

    [ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。

    [ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。

    [ STRING1 != STRING2 ] 如果字符串不相等则为真。

    [ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。

    [ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。

    [ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.

    变量用双引号的意义

    如果变量不用双引号括起来,比如echo a,那么隐含的意义就是,把a变量的字符串,按照空格、制表符、换行符等符号来分割开。然后把这些分割后的每一项再按 glob 模式展开,最后把这些值,再用一个空格重新连接起来,并打印出来。

    qilei@AFAAW-704030720:~$ cat a.sh
    #!/bin/bash
    
    a="1 2  3 4"
    echo $a
    echo "$a"
    
    输出结果
    qilei@AFAAW-704030720:~$ ./a.sh
    1 2 3 4
    1 2  3 4
    qilei@AFAAW-704030720:~$
    

    bash编程里的变量,全部用双引号括起来。这样更符合程序员的思路。

    for 循环

    for changedFilePath in ${changedFileList[@]}; do
        #do something
    done
    

    while 循环

    while read -r line;do
        cp_with_backup "${line}" "${targetPath}/"
    done <<< "$files"
    

    Linux 命令

    管道符号 |

    用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2

    eg. 将目录的文件的大小(size)从小到大进行输出

    $ls -s|sort -nr 
    

    grep与find

    grep命令用于查找文件里符合条件的字符串

    语法
    grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]
    
    # 只查找前三个匹配到的abc, 显示前后各五行
    grep -m3 -C5 "abc" file
    
    find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;
    
    // 若要在find到的文件中执行grep, 要以-exec开头,以 \;结尾。 {}是指通过find获得的结果
    find . -type f -name "*.txt" -exec grep -H "brucezhu" {} \;
    
    可以写成多个exec
    find . -type f -name "*.txt" -exec grep -H "brucezhu" {} \; -exec echo {} \;
    
    当前目录及子目录下查找所有以.py和.sh结尾的文件  
    find . -name "*.py" -o -name "*.sh"
    
    忽略某些方件
    $(find "$JRYS_SOURCE_DIR" "(" -name "*.java" ")" \
    "("  \
     -not -path "**/android/*"  \
      ")"
    

    pcregrep

    能够使用Perl Regular Expression正则查询内容的命令。(使用原始的grep无法使用断言)

    安装:brew install pcre

    sed

    可依照script的指令,来处理、编辑文本文件。

    语法
    sed [-hnV][-e<script>][-f<script文件>][文本文件]
    
    动作说明(script):

    a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
    c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
    d :删除,因为是删除,所以 d 后面通常不接任何东西;
    i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
    p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
    s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g

    eg.

    // 在testfile文件的第四行后添加一行,并将结果输出到标准输出(a\ 后面要有空格)
    sed "4 a\ 
    newline
    " testfile 
    
    // 将文件中/* compiled from: AggregateException */转成a.java:AggregateException输出
    // 语法为sed -E "s/正则表达式或内容/替换的内容/"
    grep -H "/* compiled from:" a.java | sed -E "s/:.*: (.*) \*\//:\1/"
    
    // 对文件夹下所有文件都进行文字替换(Linux与Mac的sed命令格式略有不同,mac上需加备份路径,不加备份路径时可以写成两个单线号'')
    find . -type f -name "*.txt" | xargs sed -i '' "s/brucezhu/BruceZhu/"
    

    xargs

    是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。xargs是构建单行命令的重要组件之一。

    -v参数很有用,可以反向滤除掉一些不想要的信息
    -I的用法:若文件名中用空格,会将一行作为两个元素输出(xargs以空格和换行作为输出分隔),加上-i, 就只会以每行作为一个输出元素了

    // 找到splash_launch_first相关行,且过滤掉被注释的行
    echo "$codeFiles" | xargs grep -H "splash_launch_first" | pcregrep -v "\//.*splash_launch_first"
    
    // 多行的txt文档单行输出
    cat test.txt | xargs
    // 将txt文档内容,每三个元素为一行的输出
    cat test.txt | xargs -n3
    // -d选项可以自定义一个定界符,输出name name name name
    echo "nameXnameXnameXname" | xargs -d 'X'
    // 复制所有图片文件到 /data/images 目录下
    ls *.jpg | xargs -n1 -I {} cp {} /data/images
    // xargs -0将\0作为定界符
    find . -type f -name "*.php" -print0 | xargs -0 wc -l
    // 查看所有文件的行数总和
    find . -type f | xargs wc -l
    // 查看所有java文件的总文件数
    find . (-name "*.java") | wc -l
    // -I的用法:若文件名中用空格,会将一行作为两个元素输出(xargs以空格和换行作为输出分隔),加上-i, 就只会以每行作为一个输出元素了
    echo "$files" | xargs -I {} grep -H "${content}" {} | grep -v -E "\//.*${content}" ||:
    

    history

    显示在终端所执行过的所有命令的历史

    pwd

    以绝对路径的方式显示用户当前工作目录

    // 当前执行脚本所在路径(用${BASH_SOURCE[0]}"可以实现获得当前脚本文件名)
    echo $(cd `dirname $0`; pwd)
    

    wc

    用于计算字数、行数

    tee

    用于读取标准输入的数据,并将其内容输出成文件

    // 将用户输入的数据同时保存到文件"file1"和"file2"中
    tee file1 file2
    

    计算器

    echo "1+2" | bc

    pushd和popd

    用于在两个目录之间需要频繁切换

    执行pushd ~/Desktop/shell_test/后将 ~/Desktop/shell_test/路径压入栈中,得到返回值。而且当前目录也跳转了。
    此时,再输入pushd会将栈顶目录和下一目录对调。

    popd用于将栈顶的目录弹出,此时除非再一次使用pushd压栈,否则pushd无法再找到已弹出的目录

    sort

    排序

    // 去重排序
    sort -u
    

    curl

    线上请求、下载

    curl -OL https://github.com/pmd/pmd/releases/download/pmd_releases%2F6.6.0/pmd-bin-6.6.0.zip
    

    wget

    wget命令用来从指定的URL下载文件。wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。

    scp

    将自己电脑的文件远程上传到其他电脑上
    scp 上传文件 gitlab@192.168.0.190:目标目录

    标准输出与参数的区别

    管道“|” 用来将前一个命令的标准输出传递到下一个命令的标准输入。

    xargs 将前一个命令的标准输出传递给下一个命令,作为它的参数。

    可见,标准输入与命令参数是不同的。个人理解,命令参数就是直接跟在命令后面的,标准输入可以是键盘,文件等。

    所以,管道符 | 所传递给程序的不是简单地在程序名后面输入的参数,它们会被程序内部的读取功能如scanf和gets等接收,而xargs则是将内容作为普通的参数传递给程序,相当于直接跟在命令后面。况且,有些命令是不接受标准输入的,比如kill,rm等命令。

    总结:管道符后不加xargs相当于先将xargs后面的命令回车执行一下再从键盘里输入管道符前面命令执行的结果内容

    applescript

    shell 调用 applescript的方法 (osascript <<EOF)

    osascript <<EOF
        tell application "Finder"
            set _b to bounds of window of desktop
            set _x to item 1 of _b
            set _y to item 2 of _b
            set _width to item 3 of _b
            set _height to item 4 of _b
        end tell
    
        if _y < 0 then
            set _width to 1080
            set _height to 1920
            set _x to 1440
        end if
    
        set w_height to $height
        if w_height > _height then
            set w_height to _height
        end if
    
        get _height
        get _b
        tell application "System Events" to tell application process "Beyond Compare"
            tell window 1
                set {size, position} to {{_width, w_height}, {_x, _y}}
            end tell
        end tell
    EOF
    

    备忘

    shell脚本中赋值语法 var="asdf", 等号两边不能有空格!!!!!!
    if 的判断条件 [[ -e FILE ]], 两个中括号,中括号与条件之间要有空格!!!!
    在grep后面要加||: , 否则shell脚本就不会再执行下去

    // eg.
    echo "$codeFiles" | xargs grep -H --color "splash_launch_first" ||:
    

    应用

    将查询到的数据存储到文件中

    ndk-stack -sym symbol.txt -dump crash.txt | xargs echo >> "result.txt"
    

    将所有后缀为@3x.png的图片改为后缀是.png

    for name in `ls *@3x.png`;do mv $name ${name%@3x.png}.png;done
    

    将所有后缀为@2x.png的图片删除

    for name in `ls *@2x.png`;do rm -f $name;done
    

    参考

    Linux命令大全

    http://www.runoob.com/linux/linux-command-manual.html

    相关文章

      网友评论

          本文标题:【技术整理】Shell脚本学习

          本文链接:https://www.haomeiwen.com/subject/ntejoltx.html