生信人的Linux14-24

作者: 泥人吴 | 来源:发表于2019-02-08 22:33 被阅读66次

    Liunx Day15:管道和重定向

    管道和重定向:> < >> <<

    Linux:

    >:覆盖输出
    >> : 追加输出(保留文件原有内容)
    # set -C :禁止对已经存在的文件使用覆盖重定向,强制输出覆盖则使用
    
    • >:覆盖输出
    $ ls /var
    backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp  www
    $ ls /var > /tmp/var.out
    $ cat /tmp/var.out
    backups
    cache
    crash
    lib
    local
    lock
    log
    mail
    opt
    run
    snap
    spool
    tmp
    www
    
    • 注意文件/tmp/var.out的变化,这个例子说明>覆盖输出
    $ cat /etc/fstab > /tmp/var.out
    $ cat /tmp/var.out
    /dev/vda1            /                    ext3       noatime,acl,user_xattr 1 1
    proc                 /proc                proc       defaults              0 0
    sysfs                /sys                 sysfs      noauto                0 0
    debugfs              /sys/kernel/debug    debugfs    noauto                0 0
    devpts               /dev/pts             devpts     mode=0620,gid=5       0 0
    /dev/vdb1 /public ext3 defaults 0 0
    /dev/vdc /home ext3 defaults 0 0
    #/dev/vdf /trainee ext3 defaults 0 0
    /mnt/10GiB.swap swap swap defaults 0 0
    
    • >>的追加输出作用:
    $ ls /var
    backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp  www
    $ ls /var >> /tmp/var.out
    $ cat /tmp/var.out
    /dev/vda1            /                    ext3       noatime,acl,user_xattr 1 1
    proc                 /proc                proc       defaults              0 0
    sysfs                /sys                 sysfs      noauto                0 0
    debugfs              /sys/kernel/debug    debugfs    noauto                0 0
    devpts               /dev/pts             devpts     mode=0620,gid=5       0 0
    /dev/vdb1 /public ext3 defaults 0 0
    /dev/vdc /home ext3 defaults 0 0
    #/dev/vdf /trainee ext3 defaults 0 0
    /mnt/10GiB.swap swap swap defaults 0 0
    backups
    cache
    crash
    lib
    local
    lock
    log
    mail
    opt
    run
    snap
    spool
    tmp
    www
    
    • set命令的使用:
    $ help set
    #  -C  If set, disallow existing regular files to be overwritten
              by redirection of output.
    #  Using + rather than - causes these flags to be turned off. 
    # set -C:禁止对已存在文件使用覆盖重定向。要想强制覆盖输出,则使用>|
    #set +C:关闭上述功能。
    $ ls /usr/ > /tmp/var.out
    $ cat /tmp/var.out
    bin
    games
    include
    lib
    local
    sbin
    share
    src
    $ set -C
    $ ls /usr/ > /tmp/var.out
    -sh: /tmp/var.out: cannot overwrite existing file
    $ set +C
    $ ls /usr/ > /tmp/var.out
    $ set -C
    $ ls /usr/ > /tmp/var.out
    -sh: /tmp/var.out: cannot overwrite existing file
    $ ls /usr/ >| /tmp/var.out
    # >| 的意义:强制覆盖输出
    
    • 重定向错误输出:
    # 2>
    # 2>>
    # 指定一个不存在的文件usrr,使用2>来重定向覆盖输出
    $ ls /usrr/ > /tmp/var2.out
    ls: cannot access '/usrr/': No such file or directory
    $ ls /usrr/ 2> /tmp/var2.out
    -sh: /tmp/var2.out: cannot overwrite existing file
    $ set +C
    $ ls /usrr/ 2> /tmp/var2.out
    $ cat /tmp/var2.out
    ls: cannot access '/usrr/': No such file or directory
    # 2>自对错误的有效,对于正确的则无效
    $ ls /usr/ 2> /tmp/var2.out
    bin  games  include  lib  local  sbin  share  src
    
    • 即正确/错误的连写
     ls /var > /tmp/var4.out 2> /tmp/var.out
    &> :重定向标准输出/错误输出到同一个文件中去。
    &>>:追加方式
     `<<`:Here Document
    
    $ # << :Here Doucment 在此处生成文档
    $ cat << END
    > The first line
    > THe second line
    > END
    The first line
    THe second line
    $ #EOF:END or OFF
    $ # END:此处结束标志
    $ cat >> /tmp/mayfile.txt << EOF
    > The first line
    > The second line
    > OFF
    > END
    > EOF
    $ cat /tmp/mayfile.txt
    The first line
    The second line
    OFF
    END
    $ # 可以此方式在脚本中生成文本文档
    

    管道:

    • 前一个命令的输出作为后一个命令的输出,叫做管道
      命令1 | 命令2 | 命令3
      例子:
    $ echo "hello world"
    hello world
    $ echo "hello world" | tr 'a-z' 'A-Z'
    HELLO WORLD
    $ #输出/etc/passwd 并排序sort
    $ cat /etc/passwd | sort
    amliang:x:1075:1076::/trainee/home/amliang:
    _apt:x:105:65534::/nonexistent:/bin/false
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    dbjiang:x:1085:1086::/umac/ht1T/home//dbjiang:
    dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/bin/false
    dwang:x:1103:1104::/trainee/home/dwang:
    dzhang:x:1016:1020:,,,:/home/dzhang:/bin/bash
    fxue:x:1077:1078::/trainee/home/fxue:
    ...
    
    • 对 /etc/passwd进行第一列cut并排序
    $ cut -d: -f1 /etc/passwd | sort
    amliang
    _apt
    backup
    bin
    daemon
    dbjiang
    dnsmasq
    dwang
    dzhang
    ...
    # 将上面的排序换成大写,可以进一步
    $ cut -d: -f1 /etc/passwd | sort | tr 'a-z' 'A-Z'
    AMLIANG
    _APT
    BACKUP
    BIN
    DAEMON
    DBJIANG
    DNSMASQ
    DWANG
    DZHANG
    FXUE
    FZHAO
    GAMES
    ...
    
    • 对 /etc/passwd进行第3列cut并按数值排序
    $ cut -d: -f3 /etc/passwd | sort -n
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    13
    33
    34
    38
    ...
    
    $ wc -l /etc/passwd
    80 /etc/passwd
    $ wc -l /etc/passwd | cut -d' ' -f1
    80
    
    • tee
      先看看tee的意思:
    $ man tee
    TEE(1)                              User Commands                              TEE(1)
    NAME
           tee - read from standard input and write to standard output and files
    # 所以tee可以实现将输出即保存到文件中,又可以输出到屏幕上
    

    例子:

    $ echo "Hello World" | tee /tmp/hello.world
    Hello World
    $ cat /tmp/hello.world
    Hello World
    

    练习题:

    1. 统计/usr/bin/这个目录下的文件个数
    $ ls /usr/bin/ | wc -l
    1109
    

    2.取出当前系统上所有用的shell,要求,每种shell只显示一次,并且按顺序进行排序。

    $ cut -d: -f7 /etc/passwd | sort -u
    
    /bin/bash
    /bin/false
    /bin/sync
    /usr/sbin/nologin
    

    3.显示出/var/log目录下每个文件的内容类型:
    file /var/log/*
    ls /var/log | file提示file命令不能这样用.
    4.取出/etc/inittb文件的第六行
    head -6 /etc/inittb | tail -1


    Linux Day16: grep/egrep/fgrep文本查找

    文本查找的需要:

    grep,egrep,fgrep
    grep:根据模式搜索文本,并将符合模式的文本行显示出来
    Pattern:文本字符和正则表达式的元字符所组合而成匹配条件

    grep:

    # 表达式
    SYNOPSIS
           grep [OPTIONS] PATTERN [FILE...]
           grep [OPTIONS] [-e PATTERN]...  [-f FILE]...  [FILE...]
    
    • grep的一些用法:
    $ grep 'root' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    $ man grep
    $ # -i:不区分大小写
    $ # --color 显示颜色
    $ grep --color  'root' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    $ #-v:反向匹配,显示没有被模式匹配的行
    $ grep -v  'root' /etc/passwd
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    ...
    $ # -o:只显示被模式匹配的本身
    $ grep -o 'root' /etc/passwd
    root
    root
    root
    

    正则表达式:

    Regular EXPression,REGEXP (下次课程学习)
    复习Linux Day6

    *:任意长度的任意字符
    ?:任意单个字符
    [ ] :指定范围内
    [ ^ ]:指定范围外的
    

    元字符:

    . :匹配任意单个字符
    [ ]: 匹配指定范围内的单个字符
    [ ^ ]:匹配指定范围外的单个字符
    字符集合:[ :digit:] 数字, [ :lower:] 小写,[ :upper :]大写,[ :punct:]标点符号,[:space:]空格,[:alpha:]所有字母,[:alnum:]所有字符字母
    
    \<或\b放在后面 :锚定词首, 其后面的任意字符必须作为单词首部出现
    \>或\b (放在前面): 锚定词尾,其前面的任意字符必须作为单词的尾部出现
    

    分组:\ ( \ )

    \ (ab)* 后向引用(ab)的意思

    $ # .匹配单个任意字符
    $ grep  'r..t' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    
    $ # 字符个数:* 匹配其前面的字符任意次(区别任意长度)
    
    $ # 创建一个文件text.txt
    $ nano text.txt
    $ cat text.txt
    a
    b
    ab
    adb
    amnb
    amnmnb
    amnmbmnb
    
    $ # a.*b:任意长度的任意字符(以a开头,以b结束,中间什么都可以)
    $ grep 'a.*b' text.txt
    ab
    adb
    amnb
    amnmnb
    amnmbmnb
    
    $ # a*b的意义:
    $ grep 'a*b' text.txt
    b
    ab
    adb
    amnb
    amnmnb
    amnmbmnb
    $ #匹配出了amnmbmnb:正则表达式的贪婪模式:尽可能的匹配
    
    $ # ?:做次数匹配,匹配其前面的字符1次/0次
    $ grep 'a?b' text.txt
    $ grep 'a\?b' text.txt
    b
    ab
    adb
    amnb
    amnmnb
    amnmbmnb
    $ # ?需要.'\'做转义,grep做部分匹配
    
    $ # {m,n\}在bashell中就是展开的意思,其前面加上\{}表示不展开的意思
    $ # \{m,n\}:匹配其前面的字符至少m次,至多n次
    $ grep 'a\{1,3\}b' text.txt
    ab
    $ grep 'a.\{1,3\}b' text.txt
    adb
    amnb
    amnmbmnb
    $ #grep 'a.\{1,3\}b' text.txt表示a,b之间至少包含1个字符最多出现三个字符,所以注意理解amn
    mbmnb,以及区别grep 'a\{1,3\}b' text.txt
    

    位置锚定:

    ^: 锚定行首,此字符后面的字符必须出现在行首
    $ :锚定行尾。
    `^$` : 表示空白行
    
    $ grep 'b..h$' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    ubuntu:x:500:500:ubuntu,,,:/home/ubuntu:/bin/bash
    ...
    # 查看空白行
    $ grep '^$' /etc/passwd | wc -l
    0
    

    Linux Day17:正则表达式

    REGEXP: REGular EXPression
    Pattern

    正则表达式:

    • Basic REGEXP : 基本
    • Extented REGEXP :扩展

    复习grep的用法:

    -i, --ignore-case
    -v, --invert-match
    -o, --only-matching
    # -A NUM, --after-context=NUM
    # -B NUM, --before-context=NUM
    # -C NUM, -NUM, --context=NUM
    $ cat /proc/cpuinfo
    ...
    cpu MHz     : 2399.996
    cache size  : 4096 KB
    physical id : 0
    siblings    : 16
    core id     : 15
    cpu cores   : 16
    apicid      : 15
    initial apicid  : 15
    fpu     : yes
    fpu_exception   : yes
    cpuid level : 13
    ...
    
    #以core id       : 15为目标项,展示附近。
    # -A NUM, --after-context=NUM
    
    $ grep -A 2 'core id' /proc/cpuinfo
    core id     : 0
    cpu cores   : 16
    apicid      : 0
    --
    core id     : 1
    cpu cores   : 16
    apicid      : 1
    --
    core id     : 2
    cpu cores   : 16
    apicid      : 2
    
    # -B NUM, --before-context=NUM
    $ grep -B 2 '^core id' /proc/cpuinfo
    physical id : 0
    siblings    : 16
    core id     : 0
    --
    physical id : 0
    siblings    : 16
    core id     : 1
    --
    physical id : 0
    siblings    : 16
    core id     : 2
    
    # -C NUM, -NUM, --context=NUM
    $ grep -C 2 '^core id' /proc/cpuinfo
    physical id : 0
    siblings    : 16
    core id     : 0
    cpu cores   : 16
    apicid      : 0
    --
    physical id : 0
    siblings    : 16
    core id     : 1
    cpu cores   : 16
    apicid      : 1
    

    扩展正则表达式

    + 字符匹配:.  [  ]   [ ^ ]
    + 次数匹配: *  ?  +(匹配其前面的字符至少1次) { m,n}扩展正则表达式不需要"\"
    + 位置锚定: ^  $  \<  \>
    + 分组:( ): 分组   ——  \1  \2  \3 ....不需要\转义
    + 或者: a|b: a or b (例子:C|cat表示:
    C or cat,不是Cat or cat。)后面这种应该表示为——运用分组的方法:'(C|c)at'
    
    • 练习:如何查找1-255之间的数字:
    grep -E --color '\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/>' /etc/passwd`
    或者使用`/etc/passwd | egrep --color '\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/>' 
    

    Linux 作业:新建帐户

    • 新建账户jmz,并登陆
    Last login: Mon Oct 22 22:53:31 2018 from 113.206.61.215
    ubuntu@VM-0-3-ubuntu:~$ sudo su -
    root@VM-0-3-ubuntu:~# useradd -m jmz
    root@VM-0-3-ubuntu:~# passwd jmz
    Enter new UNIX password: 
    Retype new UNIX password: 
    passwd: password updated successfully
    root@VM-0-3-ubuntu:~# ls /home
    jmz  ubuntu
    
    • 上面表示新建账户成功,利用Xshell远程登陆:Xshell→【文件】→【新建】
    jmz.PNG

    或者这种方式登陆:

    [c:\~]$ ssh jmz@132.232.152.159
    
    
    Connecting to 132.232.152.159:22...
    Connection established.
    
    登陆.PNG jmz2.PNG
    • 表示登陆成功


      jmz3.PNG

    Linux Day18: unmask/shell

    umask :遮罩码

    • 文件默认不能具有执行权限,如果算的结果中有执行权限,则其将权限加1
      在预设的情况中, root的 umask 会拿掉比较多的属性,roo的umask 默认是 022 , 这是基于安全的考虑啦~至于一般身份使用者,通常他们的 umask 为 002 ,亦保留同群组的写入权力! 其实,关亍预设 umask 的设定可以参考 /etc/bashrc 这个档案的内容。
    root@VM-0-3-ubuntu:~# umask
    0022
    $ umask
    0002
    
    • 若使用者建立为『档案』则预设『没有可执行( x )权限』,亦叧有 rw 这两个项目,也就是最大为 666 分,预设权限如下:-rw-rw-rw-
    • 若用户建立为『目录』,则由于 x 不是否可以进入此目录有关,因此默设为所有权限均开放,亦即为 777 分,预设权限如下:drwxrwxrwx
      umask:023
      文件:666-023=643
      目录:777-023=754
    $ umask 023
    $ umask
    0023
    $ touch hellosa
    $ ls -l hellosa
    -rw-r--r-- 1 ywu ywu 0 Oct 19 22:46 hellosa
    $ mkdir testdir
    $ ls -ld testdir/
    drwxr-xr-- 2 ywu ywu 4096 Oct 19 22:47 testdir/
    $ # -rw-r--r-- 644而不是643?文件默认不能具有执行权限,如果算的结果中有执行权限,则其将权限加1
    $ # drwxr-xr-- 754 
    

    站在用户登录的角度来说,SHELL的类型

    • 登陆式shell:
      1.正常通过某终端登录
      2.su - USERNAME
      3.su -1 USERNAME

    • 非登陆式shell:
      1.su USERNAME
      2.图形终端下打开的命令窗口
      3.自动执行的shell脚本

    • bash的配置文件:
      全局配置:/etc/profile, /etc/profile.d/*.sh, /etc/bashrc
      个人配置:~/ .bash_profile, ~/ .bashrc

    • proflie类的文件:
      设定环境变量
      运行命令或脚本

    • bashrc类的文件:
      设定本地变量
      定义命令别名

    • 登陆式shell如何读取配置文件
      /etc/profile --> /etc/profile.d/*.sh --> ~/ .bash_profile --> ~/ .bashrc --> /etc/bashrc

    • 非登陆式shell如何配置文件:
      ~/ .bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

    shell编程:

    • 编译器,解释器

    • 编程语言:机器语言、汇编语言、高级语言

     静态语言:编译型语言
       强类型(变量)
       事先转换成可执行格式
       + C、C++、JAVA、C#
    
    动态语言:解释型语言,on the fly
       弱类型
       边解释边执行
       PHP、SHELL、python、perl
    
    编程模型
       面向过程:Shell,C
       面向对象:JAVA,Python,perl,C++
    
    变量:内存空间,命令
    内存:编址的存储单元
    
    编程能力
       脚本编程
    

    bash变量类型:

    1.环境变量
    2.本地变量(局部变量)
    3.位置变量
    4.特殊变量

    本地变量:

    • VARNAME=VALUE:作用域为整个bash进程

    局部变量:作用域为当前shell进程及其子进程

    1.export VARNAE=VALUE
    2.VARNAME=VALUE
    3.export VANAME
    

    环境变量:

    • 作用域为当前shell进程及其子进程

    位置变量:$1,$2,...;shift:

    # 举例说明:$1\$2代表的意义:
    ./filetest.sh /etc/fastab /etc/inittab
    $1:/etc/fastab
    $2: /etc/inittab
    
    # 练习:写一个脚本
    能接受一个参数(文件路径)
    判定:此参数如果是一个存在的文件,就显示“ok”;否则显示不存在:
    ubuntu@VM-0-3-ubuntu:~$ nano filetest.sh
    ubuntu@VM-0-3-ubuntu:~$ cat filetest.sh 
    # !/bin/bash
    if [ -e $1 ];then
     echo "OK"
    else
     echo "No such file."
    fi
    ubuntu@VM-0-3-ubuntu:~$ chmod +x filetest.sh
    ubuntu@VM-0-3-ubuntu:~$ ./filetest.sh 
    OK
    ubuntu@VM-0-3-ubuntu:~$ ./filetest.sh /etc/fstab
    OK
    ubuntu@VM-0-3-ubuntu:~$ ./filetest.sh /etc/fstabb
    No such file.
    
    # 查看shift的意义:
    ubuntu@VM-0-3-ubuntu:~$ nano shift.sh
    ubuntu@VM-0-3-ubuntu:~$ cat shift.sh 
    echo $1
    shift 2
    echo $1
    shift 1
    echo $1
    ubuntu@VM-0-3-ubuntu:~$ ./shift.sh 1 2 3 4 5 6 7 
    1
    3
    4
    

    特殊变量:

    $?:上一个命令的执行状态返回值
    $#:参数的个数
    $*:参数列表

    ubuntu@VM-0-3-ubuntu:~$ nano filetest.sh
    ubuntu@VM-0-3-ubuntu:~$ cat filetest.sh 
    # !/bin/bash
    echo $#
    echo $*
    if [ -e $1 ];then
     echo "OK"
    else
     echo "No such file."
    fi
    ubuntu@VM-0-3-ubuntu:~$ ./filetest.sh /etc/fstab /etc
    2
    /etc/fstab /etc
    OK
    

    程序执行,可能有两类返回值:

    程序执行结果
    程序状态返回码(0-255):0代表正确,1-255错误执行(1,2,127系统预留)

    输出重定向:

    >
    >>
    2>
    2>>
    $>
    +撤销变量:
    unset VARNAME

    • 查看变量:
      set
    • 查看当前shell中的环境变量:
      printenv
      env
      export
    • 脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序
      shebang:魔数
      #!/bin/bash脚本的第一行必须这样写。
      而后以#开始的都被当做解释行,不运行
    root@VM-0-3-ubuntu:~# ls /var
    backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp
    root@VM-0-3-ubuntu:~# nano first.sh
    root@VM-0-3-ubuntu:~# nano first.sh
    root@VM-0-3-ubuntu:~# ls
    first.sh
    root@VM-0-3-ubuntu:~# ls -l first.sh
    -rw-r--r-- 1 root root 21 Oct 24 21:40 first.sh
    root@VM-0-3-ubuntu:~# chmod +x first.sh
    root@VM-0-3-ubuntu:~# ls -l first.sh
    -rwxr-xr-x 1 root root 21 Oct 24 21:40 first.sh
    root@VM-0-3-ubuntu:~# first.sh
    first.sh: command not found
    root@VM-0-3-ubuntu:~# echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
    root@VM-0-3-ubuntu:~# pwd
    /root
    root@VM-0-3-ubuntu:~# ./first.sh
    backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp
    
    root@VM-0-3-ubuntu:~# chmod -x first.sh
    root@VM-0-3-ubuntu:~# ls -l first.sh
    -rw-r--r-- 1 root root 21 Oct 24 21:40 first.sh
    root@VM-0-3-ubuntu:~# bash first.sh
    backups  cache  crash  lib  local  lock  log  mail  opt  run  snap  spool  tmp
    

    技能树1: 文本处理

    文本处理:

    ubuntu@VM-0-3-ubuntu:~$ cd test1/
    ubuntu@VM-0-3-ubuntu:~/test1$ less -SN test.bed
    
    ubuntu@VM-0-3-ubuntu:~/test1$ grep H3K4me1 test.bed
    chr1    9788    10497   ID=SRX539646;Name=H3K4me1%20(@%20HMEC);Title=GSM1383855:%20HMEC%20H3K4me1%20ChIP-Seq%3B%20Homo%20sapiens%3B%20ChIP-Seq;Cell%20group=Breast;<br>source_name=HMEC;cell%20line=HMEC;chip%20antibody=H3K4me1%20(#39298,%20Active%20Motif);  790    9788 10497   255,214,0
    
    ubuntu@VM-0-3-ubuntu:~/test1$ grep -n H3K4me1 test.bed
    4:chr1  9788    10497   ID=SRX539646;Name=H3K4me1%20(@%20HMEC);Title=GSM1383855:%20HMEC%20H3K4me1%20ChIP-Seq%3B%20Homo%20sapiens%3B%20ChIP-Seq;Cell%20group=Breast;<br>source_name=HMEC;cell%20line=HMEC;chip%20antibody=H3K4me1%20(#39298,%20Active%20Motif);  790    9788 10497   255,214,0
    
    • 运用管道结合cat.grep命令:
    ubuntu@VM-0-3-ubuntu:~/test1$ cat -n test.bed |grep H3K4me1
         4  chr1    9788    10497   ID=SRX539646;Name=H3K4me1%20(@%20HMEC);Title=GSM1383855:%20HMEC%20H3K4me1%20ChIP-Seq%3B%20Homo%20sapiens%3B%20ChIP-Seq;Cell%20group=Breast;<br>source_name=HMEC;cell%20line=HMEC;chip%20antibody=H3K4me1%20(#39298,%20Active%20Motif); 790  .   9788    10497   255,214,0
    
    • awk的应用:
    ubuntu@VM-0-3-ubuntu:~/test1$ cut -f 1-3 test.bed
    track name="His (@ Brs) 50" url="http://chip-atlas.org/view?id=$$" gffTags="on"
    chr1    9769    10673
    chr1    9776    10481
    chr1    9788    10497
    chr1    9795    10434
    chr1    9799    10446
    chr1    9805    10419
    chr1    9810    10438
    chr1    9811    10465
    chr1    9825    10306
    ubuntu@VM-0-3-ubuntu:~/test1$ cut -f 1-3 test.bed |awk '{print $1}'
    track
    chr1
    chr1
    chr1
    chr1
    chr1
    chr1
    chr1
    chr1
    chr1
    ubuntu@VM-0-3-ubuntu:~/test1$ cut -f 1-3 test.bed |awk '{print $1":"$2","$3}'
    track:name="His,(@
    chr1:9769,10673
    chr1:9776,10481
    chr1:9788,10497
    chr1:9795,10434
    chr1:9799,10446
    chr1:9805,10419
    chr1:9810,10438
    chr1:9811,10465
    chr1:9825,10306
    

    参考资料:linux命令行文本操作一文就够

    技能树2: 软件安装

    软件安装

    • 下载bowtie2,并调用命令
    $ wget https://sourceforge.net/projects/bowtie-bio/files/bowtie2/2.2.9/bowtie2-2.2.9-linux-x86_64.zip
    $ unzip bowtie2-2.2.9-linux-x86_64.zip
    $ ls
    bowtie2-2.2.9  bowtie2-2.2.9-linux-x86_64.zip
    $ cd bowtie2-2.2.9/
    $ ls
    AUTHORS            bowtie2-build-l      bowtie2-inspect-s    NEWS
    bowtie2            bowtie2-build-l-debug    bowtie2-inspect-s-debug  scripts
    bowtie2-align-l        bowtie2-build-s      doc          TUTORIAL
    bowtie2-align-l-debug  bowtie2-build-s-debug    example          VERSION
    bowtie2-align-s        bowtie2-inspect      LICENSE
    bowtie2-align-s-debug  bowtie2-inspect-l    MANUAL
    bowtie2-build          bowtie2-inspect-l-debug  MANUAL.markdown
    # 调用命令,采用绝对路径的方式:
    $ /umac/ht1T/home/ywu/biosoft/bowtie2/bowtie2-2.2.9/bowtie2
    No index, query, or output file specified!
    Bowtie 2 version 2.2.9 by Ben Langmead (langmea@cs.jhu.edu, www.cs.jhu.edu/~langmea)
    Usage: 
      bowtie2 [options]* -x <bt2-idx> {-1 <m1> -2 <m2> | -U <r>} [-S <sam>]
    
      <bt2-idx>  Index filename prefix (minus trailing .X.bt2).
                 NOTE: Bowtie 1 and Bowtie 2 indexes are not compatible.
      <m1>       Files with #1 mates, paired with files in <m2>.
                 Could be gzip'ed (extension: .gz) or bzip2'ed (extension: .bz2).
      <m2>       Files with #2 mates, paired with files in <m1>.
                 Could be gzip'ed (extension: .gz) or bzip2'ed (extension: .bz2).
      <r>        Files with unpaired reads.
                 Could be gzip'ed (extension: .gz) or bzip2'ed (extension: .bz2)
    ···
    
    • 安装:samtools:
    $ cd ~/biosoft
    $ pwd
    /umac/ht1T/home/ywu/biosoft
    $ mkdir samtools && cd samtools
    $ pwd
    /umac/ht1T/home/ywu/biosoft/samtools
    $ wget https://github.com/samtools/samtools/releases/download/1.3.1/samtools-1.3.1.tar.bz2 
    # 注意的是这里压缩文件格式为bz2
    $ tar xvfj samtools-1.3.1.tar.bz2
    samtools-1.3.1/
    samtools-1.3.1/aclocal.m4
    samtools-1.3.1/AUTHORS
    samtools-1.3.1/bam.c
    samtools-1.3.1/bam.h
    samtools-1.3.1/bam2bcf.c
    samtools-1.3.1/bam2bcf.h
    samtools-1.3.1/bam2bcf_indel.c
    ...
    
    
    $ cd samtools-1.3.1/
    $ ls
    aclocal.m4   bam_lpileup.c     bam_tview.c         faidx.c         sam_header.c
    AUTHORS      bam_lpileup.h     bam_tview_curses.c  htslib-1.3.1    sam_header.h
    bam2bcf.c    bam_mate.c    bam_tview.h         INSTALL         sam_opts.c
    bam2bcf.h    bam_md.c      bam_tview_html.c    install-sh      sam_opts.h
    bam2bcf_indel.c  bam_plbuf.c       bedcov.c        kprobaln.c      sample.c
    bam2depth.c  bam_plbuf.h       bedidx.c        kprobaln.h      sample.h
    bam_addrprg.c    bam_plcmd.c       ChangeLog.old       LICENSE         samtools.1
    bam_aux.c    bam_quickcheck.c  config.h.in         Makefile        samtools.h
    bam.c        bam_reheader.c    config.mk.in        Makefile.mingw  sam_view.c
    bam_cat.c    bam_rmdup.c       configure           misc        stats.c
    bam_color.c  bam_rmdupse.c     configure.ac        NEWS        stats_isize.c
    bam_endian.h     bamshuf.c     cut_target.c        padding.c       stats_isize.h
    bam_flags.c  bam_sort.c    dict.c          phase.c         test
    bam.h        bam_split.c       errmod.c        README          win32
    bam_import.c     bam_stat.c    errmod.h        sam.c
    bam_index.c  bamtk.c       exampl·es           sam.h
    $ # 里面没有samtool这样一个程序,需要make一下
    $ make
    
    $ ls
    ···
    bam_addrprg.o    bam_plbuf.o       bam_tview_html.o    kprobaln.c      samtools
    bam_aux.c    bam_plcmd.c       bam_tview.o         kprobaln.h      samtools.1
    bam_aux.o    bam_plcmd.o       bedcov.c        kprobaln.o      samtools.h
    ···
    
    • 调用bowtie2的三种方式:
    # 第一种方法:赋值,然后$bowtie2
    $ bowtie2=/umac/ht1T/home/ywu/biosoft/bowtie2/bowtie2-2.2.9/bowtie2
    $ cd 
    # 加上$符号调用
    $ $bowtie2 
    No index, query, or output file specified!
    Bowtie 2 version 2.2.9 by Ben Langmead (langmea@cs.jhu.edu, www.cs.jhu.edu/~langmea)
    Usage: 
      bowtie2 [options]* -x <bt2-idx> {-1 <m1> -2 <m2> | -U <r>} [-S <sam>]
    
      <bt2-idx>  Index filename prefix (minus trailing .X.bt2).
                 NOTE: Bowtie 1 and Bowtie 2 indexes are not compatible.
      <m1>       Files with #1 mates, paired with files in <m2>.
    ···
    
    # 第二种方法:使用alias
    # alias 'bowtie2=/umac/ht1T/home/ywu/biosoft/bowtie2/bowtie2-2.2.9/bowtie2'然后bowtie2
    
    # 第三种方法:修改PATH这个环境变量, echo $PATH  ,  export 
    $ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
    $ export PATH="$PATH:/umac/ht1T/home/ywu/biosoft/bowtie2/bowtie2-2.2.9/"
    $ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/umac/ht1T/home/ywu/biosoft/bowtie2/bowtie2-2.2.9/
    $ bowtie2
    
    

    技能树3: bowtie2

    环境变量:

    • 我的账户里面好像没有这个文件 ~/.bashrc ,所以后续bowtie2添加环境变量就未完成。
    $ cd bowtie2-2.2.9/example
    $ ls
    index  reads  reference
    $ tree -h
    .
    ├── [4.0K]  index
    │   ├── [4.0M]  lambda_virus.1.bt2
    │   ├── [1.5K]  lambda_virus.2.bt2
    │   ├── [  17]  lambda_virus.3.bt2
    │   ├── [ 12K]  lambda_virus.4.bt2
    │   ├── [4.0M]  lambda_virus.rev.1.bt2
    │   └── [1.5K]  lambda_virus.rev.2.bt2
    ├── [4.0K]  reads
    │   ├── [4.0M]  longreads.fq
    │   ├── [2.2M]  reads_1.fq
    │   ├── [2.2M]  reads_2.fq
    │   └── [9.1K]  simulate.pl
    └── [4.0K]  reference
        └── [ 48K]  lambda_virus.fa
    
    3 directories, 11 files
    
    $ less reads/longreads.fq
    @r1
    CCAGCCGGACTTCAGGCCTGCCATCCAGTTCCCGCGAAGCTGGTCTTCAGCCGCCCAGGTCTTTTTCTGCTCTGACACGACGTTATTC
    CCAGCCGGACTTCAGGCCTGCCATCCAGTTCCCGCGAAGCTGGTCTTCAGCCGCCCAGGTCTTTTTCTGCTCTGACACGACGTTATTCAGCGCCAGCGGATTATCGCCATACTGTTCCTTCAGGCGCTGTTCCGTGGCTTCCCGTTCTGCCTGCCGGTCAGTCAGCCCCCGGCTTTTCGCATCAATGGCGGCCC
    +
    7%&%E,3@->*/4>0):4)17/4A=H<3!72"$97HDB(*66B(,&$+41&A,8+=,7/216,C=2#B6!>)"?&D44/6+@))30A91BA&=@(%0&-E.1-=959!B,",,#FA94,7.B+-)2@5H;6E**#EA&;"3F920A>1:<:8F-1.<A4.-/HE$02%1>;0HA6.*@(=37<:.E93+;52+8
    # 上面为fastq的格式,一共四行
    
    • 第一行:序列标识,以‘@’开头。格式比较自由,允许添加注释等相关的描述信息,描述信息以空格分开。如示图中描述信息加入了NCBI的另一个ID名称,及长度信息
    • 第二行:表示序列信息,制表符或者空格不允许出现。一般是明确的DNA或者RNA字符,通常是大写,在一些文本文件中,小写或者大小写混杂或者含有gap符号是有特殊含义。
    • 第三行:用于将测序序列和质量值内容分离开来。以‘+’开头,后面是描述信息等,或者什么也不加。如果“+”后面有内容,该内容与第一行“@”后的内容相同;
    • 第四行:表示质量值,每个字符与第二行的碱基一一对应,按照一定规则转换为碱基质量得分,进而反映该碱基的错误率,因此字符数必须和第二行保持一致。对于每个碱基的质量编码标示,不同的软件采用不同的方案

    linux Day19:循环for while

    参数

    
    $ bash cap.sh
    cap.sh
    $ bash cap.sh p1
    cap.sh
    $ vi cap.sh
    $ bash cap.sh p1
    cap.sh p1
    $ bash cap.sh p1 p2
    cap.sh p1
    $ vi cap.sh
    $ bash cap.sh p1 p2
    cap.sh p1 p2
    $ cat cap.sh
    echo $0 $1 $2
    
    # 比较下面两者的不同
    $ vi cap.sh
    $ bash cap.sh p1 p2 p3 4 5 6 7 8 9 0 3 4
    p12
    $ cat cap.sh
    echo $12
    # “$12”输出的是“$1”的内容加上字符串“2”,所以就成了“P12”,正确的写法应该是“{$12}”。
    
    $ vi cap.sh 
    $ bash cap.sh p1 p2 p3 P4 5 6 7 8 9 0 3 4
    4
    $ cat cap.sh 
    echo ${12}
    

    通配符

    通配符.PNG

    循环:

    • 进入条件,退出条件
    • 表达式:
    for 变量 in 列表;do
        循环体
    done
    #或者:
    for 变量 in 列表
    do
         循环体
    done
    
    • 如何生成列表:
    • {1..100}
    • seq [起始数 [步进长度]] 结束数
    • 练习:写一个脚本计算1..100之间数的合
    • 第一种方法:使用for
    $ nano cap.sh
    $ bash cap.sh
    The sum is :5050.
    $ cat cap.sh
    #! /bin/bash
    #
    declare i SUM=0
    for I in {1..100}; do
      let SUM=$[$SUM+$I]  # 试试不加let
    done
    
    echo "The sum is :$SUM."
    
    • 第二种方法:使用while循环
    $ vi sh1.sh
    $ bash sh1.sh 
    The SUM is :5050.
    $ cat sh1.sh 
    #!/bin/bash
    s=o # 这是累加的变量
    i=0 # 这是累计的数值,1,2,3...
    while [ "$i" != "100" ]
    do 
      i=$(($i+1)) #每次i都会加1
      s=$(($s+$i))  #s每次都会加一次i
    done
    echo  "The SUM is :$s."
    

    while循环

    • 适用于循环次数未知的场景,要有推出条件。
    • 语法
    while CONDITION ;do
      statemet
      ...
    done
    
    • 计算{1..100}的和
    ubuntu@VM-0-3-ubuntu:~$ ./sh08.sh 
    SUM is 5050
    ubuntu@VM-0-3-ubuntu:~$ cat sh08.sh
    
    #!/bin/bahs
    #
    declare -i I=1
    declare i SUM=o
    
    while [ $I -le 100 ]; do
      let SUM+=$I
      let I++
    done
    echo "SUM is $SUM"
    

    Linux Day20:Vim

    Vim编辑器

    vi的使用

    • 鸟哥书籍:按键的说明、Vim的保存文件、恢复与打开时的警告信息
    • Vim编辑器:文本编辑器,字处理器
    nano:全屏处理
    sed:行处理
    Vim:全屏处理器,模式化编辑器
    
    # 快速定位到某行:vim +12 FILE
    # 快速定位到最后一行:vim + FILE
    # Vim+PATTERN:打开文件,定位到第一次被PATTERN匹配到的行的行首
    

    vim的模式:

    • 编辑模式(命令模式)
    • 输入模式
    • 末行模式
    • 编辑模式-->输入:
    • i: 字符前面
    • a: `字符后面
    • o: 字符所在行下方,新建一行
    • I:行的行首
    • A:行的行尾
    • O:行的上方,新建一行
    • 关闭文件

    1.末行模式关闭文件
    :q 退出
    :wq 保存并退出
    :q! 不保存并退出
    :w 保存
    :w! 强行保存
    :wq 同 :x
    2. 编辑模式下退出
    ZZ 保存并提出

    移动光标

    1.逐字字符移动:
    h 👈
    j 👉
    k 👇
    l👆
    #h移动#个字符

    2.以单词单位移动
    w 下个单词行首
    e 当前或下一个单词的词尾
    b 当前或前一个单词词首
    #w 移动#个单词

    1. 行内跳转:
      0 绝对行首
      ^行首的第一个非空白字符
      $绝对行尾

    4.行间跳转:
    #G 跳转至第#行
    G 最后一行

    5.翻屏
    Ctrl+f 向下
    Ctrl+b 向上
    Ctrl+d 向下翻半屏
    Ctrl+u 向上半屏

    6.删除单个字符
    x 三处光标所在的单个字符
    #x 删除光标所在的向后的共#个字符

    7.删除命令:d
    d命令个跳转命令组合使用
    #dw#de#db
    dd:删除当前光标所在行
    #dd:删除包括当前光标所在内的#行

    • 末行模式下:
      . : 表示当前行
      $:最后一行
      +# :向下的#行

    8.黏贴命令 p
    p

    9.复制命令 y

    • 用法同d

    10.先删除内容,再转换为输入模式
    c:用法同d

    11.替换r
    R:替换模式

    12.撤销编辑操作:u
    表示:撤销前一次编辑操作
    #u:直接撤销最忌#次操作。
    撤销最近一次撤销:Ctrl+r

    13.重复前一次编辑操作:.

    14.查找
    /pattern:首部向后查找
    ?pattern:当前光标向文件首部查找
    nN表示下一个的意思。

    15.查找并替换:
    在末行模式下使用s命令

    vim的功能

    1.块选择

    下载文件hostswegt http://linux.vbird.org/linux_basic/0310vi/hosts,然后利用vim进行编辑。
    将光标移劢到第一行的 host 那个 h 上,然后按下 [ctrl]-v ,左下角出现区块示意字样:
    v:按字符选取
    V: 按矩形选取

    $ vim hosts
    
    192.168.1.1    host1.class.net
    192.168.1.2    host2.class.net
    192.168.1.3    host3.class.net
    192.168.1.4    host4.class.net
    192.168.1.5    host5.class.net
    192.168.1.6    host6.class.net
    192.168.1.7    host7.class.net
    192.168.1.8    host8.class.net
    192.168.1.9    host9.class.net
    ~                                                                                       
    ~                                                                                       
    ~                                                                                       
    ~                                                                                       
    -- VISUAL BLOCK --                                                    1,16          All
    

    此时你可以按下『y 』来进行行复制,当你按下 y 后,反白的区块就消失!

    1. 最后,将光标移到第一行行最右边,并且再用编辑模式向右按两个空格键,回到一般模式后,再按下『p 』后,如下图所示:
    $ vim hosts
    
    192.168.1.1    host1.class.net  host1
    192.168.1.2    host2.class.net  host2
    192.168.1.3    host3.class.net  host3
    192.168.1.4    host4.class.net  host4
    192.168.1.5    host5.class.net  host5
    192.168.1.6    host6.class.net  host6
    192.168.1.7    host7.class.net  host7
    192.168.1.8    host8.class.net  host8
    192.168.1.9    host9.class.net  host9
    ~                                                                                       
    ~                                                                                       
    ~
    

    2.多文本编辑

    • 复制某个文件的部分内容到另一个文件
    # 复制hosts前四行IP数据到/etc/hosts
    $ vim hosts /etc/hosts
    $ vim hosts /etc/hosts
    2 files to edit
    
    192.168.1.1    host1.class.net
    192.168.1.2    host2.class.net
    192.168.1.3    host3.class.net
    192.168.1.4    host4.class.net
    192.168.1.5    host5.class.net
    192.168.1.6    host6.class.net
    192.168.1.7    host7.class.net
    192.168.1.8    host8.class.net
    192.168.1.9    host9.class.net
    ~                                                                                                                   
    ~                                                                                       
    "hosts" 9L, 279C                                                      1,1           All
    # :files查看编辑的文件数据
    ~                                                                                       
    ~                                                                                       
    :files
    1 %a   "hosts"                        line 1
     2      "/etc/hosts"                   line 0
    Press ENTER or type command to continue
    # 按下任意键回到vim的一般模式
    #想要复制前四行,输入4yy,显示如下
    4 lines yanked  
    # 输入:n来到第二个编辑文件
    ::1     localhost ip6-localhost ip6-loopback
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    ~                                                          ~  
    #"G"定位到最后一行,"p"复制
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    192.168.1.1    host1.class.net
    192.168.1.2    host2.class.net
    192.168.1.3    host3.class.net
    192.168.1.4    host4.class.net
    :next 切换到下一个文件
    :prev 切换到前一个文件
    :last 切换到最后一个文件
    :first 切换到第一个文件
    #"u"还原原来的文件
    #"q"离开vim的多文本编辑
    `qa`:离开所有文件
    

    3.多窗口功能:

    • 分屏显示一个文件
      Ctrl+w,s:水平拆分窗口
      Ctrl+w,v:垂直
      在窗口间切换光标
      Ctrl+w,方向键
    • 多窗口编辑多个文件
      vim -o :水平分割显示
      vim -O:垂直分割显示

    以下末行模式下

    • 将当前文件中部分内容另存到另一个文件
      末行模式下使用w命令
      :w
      :ADDR1,ADDR2w /path/to/somewhere

    • 将另一个文件内容填充到目前文件下
      :r /path/to/somewhere

    • 跟shell交互
      :!COMMAND

    高级话题

    • 显示或取消行号
      : set nu
      : set nonu
    • 显示忽略大小写或区分
      : set ic (ignorecase)
      : set noic (noignorecase)
    • 设置自动缩进
      : set atuoindent
      : set ai
      : set noai
    • 查找到的文本高亮显示或取消
      : set hlsearch
      : set nohlsearch
    • 语法高亮与关闭
      : syntax on
      : syntax off
    • 配置文件
      /etc/vimrc:全部用户
      ~/.vimrc:当前用户
    #主要就是:sp{filename}的使用
    $ vim /etc/man.config 
    
    ~                                                                                       
     # 在终端在视觉要明显很多                                                                                    
    {hosts}                                                               0,0-1          All
    
    ~                                                                                                                                                                           
    /etc/man.config                                                       0,0-1          All
    "{hosts}" [New File]
    

    4.vim的常用命令示意图

    • 最后附上无敌的vim的常用命令示意图
    • 记住:是一般模式下


      马哥

    Linux Day21:grep/sed/awk

    grep

    基础正则表达式

    • 下载练习文件wget http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt
    $ vim regular_express.txt 
    $ grep -n 'the' regular_express.txt 
    8:I can't finish the test.
    12:the symbol '*' is represented as start.
    15:You are the best is mean you are the no. 1.
    16:The world <Happy> is the same with "glad".
    18:google is the best tools for search keyword.
    # 将关键字显示颜色
    $ grep -n  --color=auto 'the' regular_express.txt 
    8:I can't finish the test.
    12:the symbol '*' is represented as start.
    15:You are the best is mean you are the no. 1.
    16:The world <Happy> is the same with "glad".
    18:google is the best tools for search keyword.
    # 每次都加上--color=auto显得麻烦,使用alias来处理
    $ alias grep='grep --color=auto'
    $ source ~/.bashrc
    # 反向选择
    $ grep -vn 'the' regular_express.txt
    # 取得不论大小写的the
    $ grep -in 'the' regular_express.txt
    
    • 一些字符串的意义
      1.[^]:反向选择 ^[ ]:定位在行首的意义 ^[ ^ ]
    1. [^[:lower:]] 与 [^a-z] 意义相同
    • 找出行尾结束为小数点(.)的哪一行
    #小数点具有其它的意义,所以需要( \ )进行转意,消除特殊意义
    $ grep '\.$' regular_express.txt 
    "Open Source" is a good mechanism to develop programs.
    apple is my favorite food.
    Football game is not use feet only.
    this dress doesn't fit me.
    motorcycle is cheap than car.
    This window is clear.
    the symbol '*' is represented as start.
    You are the best is mean you are the no. 1.
    The world <Happy> is the same with "glad".
    I like dog.
    google is the best tools for search keyword.
    go! go! Let's go.
    
    • 找出空白的一行
      grep -n '^$' regular_express.txt
    • . 小数点:代表一定有一个任意字符的意思
    • (* 星号 ):代表重复前一个0到无穷多次的意思,为组合形态
    • “ .* "就代表 0个或者 多个任意字符的意思

    sed(流编辑器)

    NAME
           sed - stream editor for filtering and transforming text
    
    SYNOPSIS
           sed [OPTION]... {script-only-if-no-other-script} [input-file]...
    # 马哥: sed 'AddressCommand' file ...
    # Address:
    1. startLine ,Endline,比如:1,100;$:最后一行;$-1,倒数第二行。
    2. /RegExp/,比如:/^root/
    $ sed '/oot/d' /etc/fstab
    3. /pattern1/,/pattern2/;第一行被pattern1匹配到的行开始,至第一次被pattern2匹配到的行结束,这中间的所有行
    4. LineNumber:指定的行
    5. StartLine,+N:从startLine开始,向后的N行;
    
    • sed: Stream EDitor;行编辑器(全屏编辑器:vi)
    • sed:模式空间,默认 不编辑源文件,仅对模式空间中的进行编辑。
    • 先认识一下sed的基本参数及功能


      niaoge.PNG
      鸟哥.PNG
    • 以行为单位的新增/删除功能
    #将 /etc/passwd 的内容列出且打印行号,同时,请将第 2~5 行删
    除!
    ubuntu@VM-0-3-ubuntu:~$ nl /etc/passwd | sed '2,5d'
         1  root:x:0:0:root:/root:/bin/bash
         6  games:x:5:60:games:/usr/games:/usr/sbin/nologin
         7  man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
         8  lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    
    # 只删除第二行
    ubuntu@VM-0-3-ubuntu:~$ nl /etc/passwd | sed '2d'
         1  root:x:0:0:root:/root:/bin/bash
         3  bin:x:2:2:bin:/bin:/usr/sbin/nologin
    
    # 若是要删除第 3 到最后一行,则是『nl /etc/passwd | sed '3,$d' 』啦,那个钱字号『$ 』代表最后一行!
    
    # 在第二行后面加入两行字,例如『Drink tea or .....』『drink beer?』
    ubuntu@VM-0-3-ubuntu:~$ nl /etc/passwd | sed '2a Drink tea or ......\
    > > drink beer ?'
         1  root:x:0:0:root:/root:/bin/bash
         2  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    Drink tea or ......
    > drink beer ?
         3  bin:x:2:2:bin:/bin:/usr/sbin/nologin
    # 重点是『我们可以新增不只一行喔!可以新增好几行』但是每一行之间都必须要以反斜杠『\ 』来进行新增的行!所以,上面的例子中,我们可以仅现在第一行癿最后面就有 \ 存在啦!
    # \n:可用于换行
    
    • 部分数据的查找并替换的功能
      sed 's/要替换的/新的内容/g',通常配合正则表达式进行学习。
    • -p:打印的意思,配合-n:禁模
    • -r FILE:将指定的文件的内容添加至符合条件的行处
    • w FILE:将地址指定范围内的内容另存至...
    • s/pattern/string/:查找并替换,默认只替换第一次被模式匹配到的字符串;可以加修饰:g:全局替换;i:忽略大小写;[ s/ / /;s# # #;s@ @ @是一个意思,只是后面两个无需转义]
    • &:引用模式
    ubuntu@VM-0-3-ubuntu:~$ nano sed.sh
    ubuntu@VM-0-3-ubuntu:~$ cat sed.sh 
    hello,like
    hi,my love
    # 将like-->liker;love-->lover
    ubuntu@VM-0-3-ubuntu:~$ sed 's#l..e#&r#' sed.sh 
    hello,liker
    hi,my lover
    # 或者后向引用:
    ubuntu@VM-0-3-ubuntu:~$ sed 's#\(l..e\)#\1r#' sed.sh 
    hello,liker
    hi,my lover
    # 将like-->Like;love-->Love
    ubuntu@VM-0-3-ubuntu:~$ sed 's#l\(..e\)#L\1#g' sed.sh 
    hello,Like
    hi,my Love
    ubuntu@VM-0-3-ubuntu:~$ sed 's#l\(..e\)#L\1#' sed.sh 
    hello,Like
    hi,my Love
    

    awk

    • 相较与 sed 常常作用于一整个行的处理, awk 则比较倾向于一行当中分成数个『字段』来处理。因此,awk 相当的适合处理小型的数据处理!awk 通常运作的模式:
      `awk '条件类型 1{动作 1} 条件类型 2{动作 2} ...' filename
    ubuntu@VM-0-3-ubuntu:~$ last -n 5 
    ubuntu   pts/0        218.70.16.106    Wed Nov  7 14:40   still logged in
    ubuntu   pts/1        119.86.113.106   Fri Nov  2 23:18 - 02:05  (02:47)
    ubuntu   pts/0        113.205.193.254  Fri Nov  2 21:17 - 01:26  (04:08)
    ubuntu   pts/0        218.70.16.106    Fri Nov  2 18:50 - 18:54  (00:04)
    ubuntu   pts/0        218.70.16.106    Fri Nov  2 15:40 - 18:47  (03:07)
    
    wtmp begins Fri Nov  2 13:13:25 2018
    
    # 选去第一行、第三列
    ubuntu@VM-0-3-ubuntu:~$ last -n 5 | awk '{$1 "\t" $3}'
    # 忘了加上print
    ubuntu@VM-0-3-ubuntu:~$ last -n 5 | awk '{print $1 "\t" $3}'
    ubuntu  218.70.16.106
    ubuntu  119.86.113.106
    ubuntu  113.205.193.254
    ubuntu  218.70.16.106
    ubuntu  218.70.16.106
    # 默认的字符的分隔符为空格键或[TAB]键
    
    • awk的逻辑判断
    # 在 /etc/passwd 当中是以冒号 ":"来作为字段癿分隔,
    # 该档案中第一字段为账号,第三字段则是 UID。
    # 那假设我要查阅,第三栏小于 10 以下的数据,并且仅列出账号的第三栏, 那么可以这样做:
    ubuntu@VM-0-3-ubuntu:~$ cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}'
    root:x:0:0:root:/root:/bin/bash 
    daemon  1
    bin 2
    sys 3
    sync    4
    games   5
    man 6
    lp  7
    mail    8
    news    9
    # 第一行并未正确显示:
    # 这是因为我们读入第一行的时候,那些发数 $1,$2... 默认还是以空格键为分隔的,所以虽然我们定义了 FS=":" 了, 但是即仅能在第二行后才开始生效。那么怎么办呢?我们可以预先设定 awk 的变量, 利用 BEGIN 这个关键:
    ubuntu@VM-0-3-ubuntu:~$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
    root    0
    daemon  1
    bin 2
    sys 3
    sync    4
    games   5
    man 6
    lp  7
    mail    8
    news    9
    

    最后强烈推荐:


    Linux Day22:条件判断+if+case

    命令的间的逻辑关系:

    • 逻辑与:&& (前面第一个条件为假时,第二个条件不再判断,最终结果已经显现;第一个条件为真,第二个条件必须判断)
    root@VM-0-3-ubuntu:~# id user1
    uid=1000(user1) gid=1000(user1) groups=1000(user1)
    root@VM-0-3-ubuntu:~# id user1 &> /dev/null && echo "Hello,student"
    Hello,student
    root@VM-0-3-ubuntu:~# id student2 &> /dev/null && echo "Hello,student"
    root@VM-0-3-ubuntu:~# useradd student2
    root@VM-0-3-ubuntu:~# id student2 &> /dev/null && echo "Hello,student"
    Hello,student
    
    • 逻辑或:| |

    • 如果用户不存在user6,就添加用户user6
      ! id user6 && useradd user6
      id user6 | | useradd user6

    root@VM-0-3-ubuntu:~# id user6
    id: ‘user6’: no such user
    root@VM-0-3-ubuntu:~# id user6 || useradd user6
    uid=1008(user6) gid=1008(user6) groups=1008(user6)
    

    后续学习:if ;then;else

    if:

    • 单分支的if语句:
    if  判断条件;then
      statement1
      statement2
      ...
    fi
    
    • 双分支的if语句:
    if 判断条件;then
      statement1
      statement2
       ...
    else
      statement3
      statement4
       ...
    fi
    # 判断user1是否存在并显示出来:
    root@VM-0-3-ubuntu:/home/ubuntu# nano sh03.sh
    root@VM-0-3-ubuntu:/home/ubuntu# chmod +x sh03.sh
    root@VM-0-3-ubuntu:/home/ubuntu# ./sh03.sh
    user1 exist.
    root@VM-0-3-ubuntu:/home/ubuntu# cat sh03.sh
    #! /bin/bash
    #
    NAME=user1
    if id $NAME &> /dev/null;then
     echo "$NAME exist."
    else
     echo "$NAME not exist."
    fi
    
    # 用户不存在时,则添加一个
    root@VM-0-3-ubuntu:/home/ubuntu# ./sh03.sh
    add user5 finished.
    root@VM-0-3-ubuntu:/home/ubuntu# cat sh03.sh
    #! /bin/bash
    #
    NAME=user5
    if id $NAME &> /dev/null;then
     echo "$NAME exist."
    else
     useradd $NAME
     echo $NAME | passwd --stdin $NAME &> /dev/null
     echo "add $NAME finished."
    fi
    root@VM-0-3-ubuntu:/home/ubuntu# ./sh03.sh
    user5 exist.
    
    # 理解&>的意思,那么将其删除看看有什么效果。
    root@VM-0-3-ubuntu:/home/ubuntu# nano sh03.sh
    root@VM-0-3-ubuntu:/home/ubuntu# cat sh03.sh
    #! /bin/bash
    #
    NAME=user5
    if id $NAME ;then
     echo "$NAME exist."
    else
     useradd $NAME
     echo $NAME | passwd --stdin $NAME &> /dev/null
     echo "add $NAME finished."
    fi
    root@VM-0-3-ubuntu:/home/ubuntu# ./sh03.sh
    uid=1011(user5) gid=1011(user5) groups=1011(user5)
    user5 exist.
    root@VM-0-3-ubuntu:/home/ubuntu# nano sh03.sh
    
    • 多分支 if 的语句:
    if 判断条件1;then
      statement1
      ...
    elif 判断条件2;then
      ...
    elif 判断条件3;then
      ...
    fi
    

    一个小练习:if+for

    root@VM-0-3-ubuntu:/home/ubuntu# ./sh06.sh
    user1 exsits
    user2 exsits
    user3 exsits
    Add user4 access
    user5 exsits
    user6 exsits
    Add user7 access
    Add user8 access
    Add user9 access
    user10 exsits
    root@VM-0-3-ubuntu:/home/ubuntu# cat sh06.sh 
    # !/bin/bash
    #
    for I in {1..10};do
     if id user$I &> /dev/null;then
      echo "user$I exsits"
     else
      useradd user$I
      echo user$I | passwd --stdin user$I &> /dev/null
      echo "Add user$I access"
     fi 
    done
    

    提前结束进程exit

    • exit # 如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码。

    测试脚本是否有语法错误

    • bash -n 脚本
    • bash -x 脚本:单步执行。

    case

    • case 语句:选择结构
    case SWITH in
    value1)
      statement
      ...
      ;;
    value2)
      statement
      ...
      ;;
    *)
      statement
      ...
      ;;
    esac
    
    • 练习:
    ubuntu@VM-0-3-ubuntu:~$ vim case.sh
    ubuntu@VM-0-3-ubuntu:~$ cat case.sh 
    #/bin/bash
    #
    case $1 in
    [0-9])
     echo "A digit" ;;
    [a-z])
     echo "Lower" ;;
    [A-Z])
     echo "Upper" ;;
    *)
     echo "special character" ;;
    esac
    ubuntu@VM-0-3-ubuntu:~$ bash -n case.sh 
    ubuntu@VM-0-3-ubuntu:~$ chmod +x case.sh 
    ubuntu@VM-0-3-ubuntu:~$ ./case.sh 9
    A digit
    ubuntu@VM-0-3-ubuntu:~$ ./case.sh a
    Lower
    ubuntu@VM-0-3-ubuntu:~$ ./case.sh A
    Lower
    ubuntu@VM-0-3-ubuntu:~$ ./case.sh !
    special character
    ubuntu@VM-0-3-ubuntu:~$ ./case.sh B
    Lower
    # 想想为什么此处的A/B都显示为lower?
    # 如果换成if该如何写?
    
    # 添加用户tom
    ubuntu@VM-0-3-ubuntu:~$ id tom
    id: ‘tom’: no such user
    
    ubuntu@VM-0-3-ubuntu:~$ ./adduser.sh -v
    adduser tom finished
    ubuntu@VM-0-3-ubuntu:~$ cat adduser.sh 
    #!/bin/bash
    #
    DEBUG=0
    
    case $1 in
    -v|--verbose)
      DEBUG=1 ;;
    esac
    
    useradd tom &>/dev/null
    [ $DEBUG -eq 1 ] && echo "adduser tom finished"
    

    Linux Day23:let

    shell中如何进行算术运算:

    • let 算术运算表达式:let C=$A+$B
    root@VM-0-3-ubuntu:/home/ubuntu# A=3
    root@VM-0-3-ubuntu:/home/ubuntu# B=6
    root@VM-0-3-ubuntu:/home/ubuntu# C=$A + $B
    +: command not found
    # 周围我添加了空格
    root@VM-0-3-ubuntu:/home/ubuntu# C=$A+$B
    root@VM-0-3-ubuntu:/home/ubuntu# echo $C
    3+6
    root@VM-0-3-ubuntu:/home/ubuntu# let C=$A+$B
    root@VM-0-3-ubuntu:/home/ubuntu# echo $C
    9
    
    • $ [ 算术运算表达式]C=$[$A+$B]
    • $(($A+$B))
    • expr 算术表达式:表达式中各操作数及运算符之间要有空格,而且要使用命令引用:F=exper $A + $B

    曾经使用过for循环计算{1..100}之间的和:

    $ nano cap.sh
    $ bash cap.sh
    The sum is :5050.
    $ cat cap.sh
    #! /bin/bash
    #
    declare i SUM=0
    for I in {1..100}; do
      let SUM=$[$SUM+$I]  # 试试不加let
    done
    
    echo "The sum is :$SUM."
    

    let的进一步学习:

    let I=$[$I+1]
    SUM=$[$SUM+SI]相当于 let SUM+=$I
    let I+=1 相当于 let I++(只能每次都是加一才能使用++
    # 变量I减去/加上/乘以/除以某个数。并保存回变量I中:
    ubuntu@VM-0-3-ubuntu:~$ I=10
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    10
    ubuntu@VM-0-3-ubuntu:~$ let I++
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    11
    ubuntu@VM-0-3-ubuntu:~$ let I-=1
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    10
    ubuntu@VM-0-3-ubuntu:~$ let I-=1
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    9
    ubuntu@VM-0-3-ubuntu:~$ let I*=3
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    27
    ubuntu@VM-0-3-ubuntu:~$ let I/=3
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    9
    ubuntu@VM-0-3-ubuntu:~$ let I%=3
    ubuntu@VM-0-3-ubuntu:~$ echo $I
    0
    

    求1..100之间偶数/奇数的和,并显示出来:

    ubuntu@VM-0-3-ubuntu:~$ ./sh07.sh
    EVENSUM=2550
    ODDSUM=2500
    ubuntu@VM-0-3-ubuntu:~$ cat sh07.sh
    #/bin/bash
    #
    declare -i EVENSUM=0
    declare -i ODDSUM=0
    for I in {1..100}; do
     if [ $[ $I%2 ] -eq 0 ];then
      let EVENSUM+=$I
     else
      let ODDSUM+=$I
     fi
    done
    echo "EVENSUM=$EVENSUM"
    echo "ODDSUM=$ODDSUM"
    

    Linux Day24:条件测试

    bash中如何实现条件判断?

    • 条件测试类型:整数测试,字符测试,文件测试
    • 条件测试的表达式:
      [ expression ]
      [ [ expression ] ]
      test expression
    • 整数比较:
      -eq:测试两个整数是否相等:比如 $A -eq $B
    root@VM-0-3-ubuntu:~# A=3
    root@VM-0-3-ubuntu:~# B=6
    root@VM-0-3-ubuntu:~# [ $A -eq $B ]
    root@VM-0-3-ubuntu:~# echo $?
    1
    root@VM-0-3-ubuntu:~# B=3
    root@VM-0-3-ubuntu:~# [ $A -eq $B ]
    root@VM-0-3-ubuntu:~# echo $?
    0
    

    -ne: 测试是否不等
    -gt: 测试是否大于
    -lt:是否小于
    -ge:大于或等于
    -le:小于或等于

    • 组合测试条件
      -a:与关系
      -o:或关系
      !: 非关系
    if  [ $# -gt 1 -a $# -le 3 ]
    if  [ $# -gt 1 ] && [ $# -le 3 ]
    

    文件测试:

    -e FILE:测试文件是否存在
    -f FILE:测试文件是否为普通文件
    -d FILE:测试指定路径是否为目录
    -r ...:当前用户对指定文件是否有读取权限
    -w ...
    -x ...
    [ -e /etc/inittab ]

    # 文件不存在则退出,存在则继续执行后续命令
    # ! /bin/bash
    FILE = etc/inittab
    if  [ ! -e $FILE ]; then
      echo " No file"
      exit 5
    fi
    # 文件存在则执行后续...
    

    字符测试:

    • ==测试是否相等,等号两端要有空客
    • !=测试是否不等
    • > <
    • -n string:测试指定字符串是否为空
    • -z string:测试指定字符串是否不等

    Linux Day25:文件查找

    文件查找

    locate:

    • 非实时,查找是根据系统文件数据库进行的
    • 模糊匹配

    updatedb:

    • 手动生成文件数据库
    • 速度快

    find

    • 实时,精确
    • 支持众多查找标准
    • 遍历指定目录中的所有文件完成查找,速度慢
    • 查找路径:默认当前目录
    • 查找标准:默认为指定路径下所有文件
    • 处理运作:默认为显示
    • 匹配标准
    -name 'FILENAME': 对文件名作精确匹配,文件名统配(支持正则表达式)
    
    -iname  'FILENAME': 文件名匹配时不区分大小写
    
    -regex PATTERN:基于正则表达式进行文件名匹配
    
    -user USERNAME:根据属主查找
    -group GROUPNAME:更加属组查找
    
    -uid UID
    -gid GID
    -nouser:查找没有属主的文件
    -nogroup:
    
    -type:根据文件类型来查找
    f:普通文件
    d:目录
    c:字符
    b
    l
    s
    -size:文件大小来查找
    #k  或 [ + | - ]#k
    #M
    #G
    
    根据时间查找
    -mtime
    -ctime
    -atime
    
    根据权限查找:
    -perm MODE:
      /MODE:任意一位匹配即满足条件
      -MODE:文件权限能完全包含此mode时才符合条件(644与755)
    
    组合条件:
    -a
    -o
    -not
    

    find 运作:

    NAME
           find - search for files in a directory hierarchy
    
    SYNOPSIS
           find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]
    -print:显示
    -ls:类似ls -l的形式显示每一个文件的详细
    -ok COMMAND {} \;
    -exec COMMAND  {} \;
    find /etc -size +1M -exec echo {} >> /tmp/etc \;
    find /etc -size +1M | xargs echo >> /tmp/etc 
    

    Linux Day26:特殊权限

    SUID

    • 运行某程序时,相应进程的属主是程序文件自身的属主,而不是启动者
      chmod u+s FILE
    • 如果FILE本身就有执行权限,则SUID显示为s,否则显示为S。

    SGID

    • 运行某程序时,相应进程的属主是程序文件自身的属组,而不是启动者所属的基本组
    chmod g+s FILE
    chmod g-s FILE
    

    Sticky

    • 在一个公共目录,每个用户都可以创建、删除自己的文件,但是不能删除别人的
    chmod o+t DIR
    chmod o-t DIR
    
    000:
    001
    ...
    110:
    111:
    # chmod 2755 /tmp.test
    unmask 0022
    

    FACL

    • 文件系统访问控制列表
    • 利用文件扩展保存额外的访问控制权限
    setfacl
      -m: 设定
    # setfacl -m u:hadoop:rw inittab
      -x:取消
         u:UID:perm
         g:
    # setfacl -x u:hadoop:rw inittab
    getfacl
    
    • 访问文件:
      默认情况下:Owner👉 Group 👉 Other
      FACL:Owner👉 facl,user 👉 Group 👉 facl,group

    Linux Day27:Linux 压缩、解压缩命令

    压缩格式:

    • 格式:gz,bz2,xz,zip,z
    • 只能压缩文件,压缩后默认会删除源文件

    gzip

    gzip: .gz
    gzip /PATH/to/somefile 
      -d: 表示解压缩的意思(gunzip)
      -#:1-9,指定压缩比,默认为6
    
    gunzip:
    gunzip /PATH/to/somefile .zp
    

    bzip2: .bz2

    • 比gzip有更大压缩比的压缩工具,使用格式相似
    bzip2  /PATH/to/somefile 
      -d: 表示解压缩的意思
      -k: 压缩时保留源文件
      -#:1-9,指定压缩比,默认为6
    
    bunzip2:
    

    xz: .xz

    • 用法一样
    NAME
           xz, unxz, xzcat, lzma, unlzma, lzcat - Compress or decompress .xz and .lzma files
    
    SYNOPSIS
           xz [option]...  [file]...
    

    cat/zcat

    • zcat /PATH/to/somefile.gz:不解压的情况,查看文本文件的内容:

    zip:归档+压缩

    • 具有压缩目录的功能
    • zip filename,zip file1 file2,多个文件都可压缩到filename.zip中,具有归档的意义。
    • archive:归档,归档本身不意味着压缩。

    tar:

     只归档,不压缩
      -c :创建归档文件
      -f file.tar:操作的归档文件
      -x:展开归档文件
      --xattrs:归当时,保留文件的扩展属性信息。
      
      -zcf:归档并调用gzip压缩
      -zxf:调用gzip解压缩并展开归档,-z此处可省略
    
      -jcf:调用bzip2
      -jxf: 
    
      -Jcf:  调用xz
      -Jxf:
    
      -t:不展开归档,直接查看归档的文件,和-f 一起用。
      -jtf:展开
    tar -cf test.tar test*.txt
    tar -xf test.tar
    
    • cpio:归档工具

    read

    ubuntu@VM-0-3-ubuntu:~$ ./sum.sh 
    Input two intergers:2 3
    5
    ubuntu@VM-0-3-ubuntu:~$ cat sum.sh 
    #!/bin/bash
    #
    echo -n "Input two intergers:"
    read A B
    echo "$[ $A + $B ]"
    
    使用read -p
    Input two intergers:2 3
    5
    ubuntu@VM-0-3-ubuntu:~$ cat sum.sh 
    #!/bin/bash
    #
    #echo -n "Input two intergers:"
    read -p "Input two intergers:" A B
    echo "$[ $A + $B ]"
    
    • 写一个脚本,压缩三个文件大一个文件中:
    # 首先查看文件中的内容
    ubuntu@VM-0-3-ubuntu:~$ ls
    a                c                    second.sh.save   sh06.sh.new.new   test.bed.new.new
    adduser.sh       cap.sh               sed.sh.new.new   sh07.sh.new.new   test.new.new
    awk.new.new      case.sh              sh03.sh          shift.sh.new.new  third.sh.new.new
    b                d.new.new            sh04.sh.new.new  sum.sh
    biosoft.new.new  filetest.sh.new.new  sh05.sh.new.new  test1.new.new
    
    # 编写脚本
    ubuntu@VM-0-3-ubuntu:~$ cat maycar.sh 
    # !/bin/bash
    #
    read -p "Three files:" file1 filie2 file3
    read -p "Destination:" DEST
    
    tar -jcf ${DEST}.tar.bz2 $file1 $file2 $file3
    
    # 执行脚本:
    ubuntu@VM-0-3-ubuntu:~$ ./maycar.sh 
    Three files:cap.sh case.sh sh03.sh
    Destination:DEST
    ubuntu@VM-0-3-ubuntu:~$ ls
    a                c             filetest.sh.new.new  sh04.sh.new.new   sum.sh
    adduser.sh       cap.sh        maycar.sh            sh05.sh.new.new   test1.new.new
    awk.new.new      case.sh       second.sh.save       sh06.sh.new.new   test.bed.new.new
    b                DEST.tar.bz2  sed.sh.new.new       sh07.sh.new.new   test.new.new
    biosoft.new.new  d.new.new     sh03.sh              shift.sh.new.new  third.sh.new.new
    
    # 展开压缩文件查看:
    ubuntu@VM-0-3-ubuntu:~$ tar -tf DEST.tar.bz2 
    cap.sh
    sh03.sh
    # 为什么只有两个文件呢?
    
    • 将上面的脚本升级,为用户提供可选择的压缩方式:
    # !/bin/bash
    #
    read -p "Three files:" file1 filie2 file3
    read -p "Destination:" DEST
    resd -p "Compress[gzip|bzip2|xz]:" comp
    
    case $comp in
    gzip)
      tar -zcf ${DEST}..tar.bz2 $file1 $file2 $file3 ;;
    bzip2)
      tar -jcf ${DEST}.tar.bz2 $file1 $file2 $file3 ;;
    xz)
      tar -cf ${DEST}.tar.bz2 $file1 $file2 $file3
      xz ${DEST}.tar ;;
    *) 
      echo "Unkown"
      exit 7
      ;;
    esac
    

    复习脚本编程

    顺序结构
    选择结构
      if
      case
    循环结构
      for
      while
      until
    

    生信技能树公益视频合辑:学习顺序是linux,r,软件安装,geo,小技巧,ngs组学!
    请猛戳下面链接
    B站链接:https://m.bilibili.com/space/338686099

    YouTube链接:https://m.youtube.com/channel/UC67sImqK7V8tSWHMG8azIVA/playlists

    生信工程师入门最佳指南:https://mp.weixin.qq.com/s/vaX4ttaLIa19MefD86WfUA

    学徒培养:https://mp.weixin.qq.com/s/3jw3_PgZXYd7FomxEMxFmw

    相关文章

      网友评论

        本文标题:生信人的Linux14-24

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