【Linux 笔记】Linux 基本操作 - 02. shell编程基础

笔记接上篇【Linux 笔记】Linux 基本操作 - 01. 系统认知-文本处理-软件安装-环境变量。笔记大部分源于生信技能树的B站视频教程【生信技能树】生信人应该这样学linux(更新至第14集),如有需要,可去欣赏原汁原味的视频讲解。8. shell编程基础(1) 变量1) 环境变量环境变量会在当前Shell和这个Shell的所有子Shell当中生效。① 设置全局环境变量:export 变量名=变量值② 查看环境变量:env③ 查看变量内容:echo $变量名④ 删除变量: unset 变量名⑤ 常见系统预定义环境变量:HOME 、PWD、PATH 、PS1echo $HOME #显示主目录echo $PWD #显示当前工作目录echo $PATH #显示系统查找命令的路径echo $PS1 #显示已设置的系统提示符变量# \[\e[32;1m\]\u \[\e[33;1m\]\t \[\e[35;1m\]\w \n\[\e[0;40m\]$

PS1:变量说明\d显示日期,格式为 “星期 月 日”\h显示简写主机名。如,默认主机名 “localhost”\t显示24小时制时间,格式为 “HH:MM:SS”\T显示12小时制时间,格式为 “HH:MM:SS”\A显示24小时制时间,格式为 “HH:MM”\u显示当前用户名\w显示当前用户所在目录的完整名称\W显示当前所在目录的最后一个目录#执行的第几个命令$提示符。如果是root用户会显示提示符为 “#”,如果是普通用户则会显示提示符为“$”。例如:[root@bogon ~]# PS1="[\u@\t \w]$ " :\u:代表root;\t代表24小时制时间;\w(w小写表示绝对路径)。2) 位置参数变量→写入到脚本文件内echo $12 #"$1"为变量,"2"为一个字符串;故,"$12"输出为"$1"的内容加上字符串2echo ${12} #变量"$12"位置参数变量作用$nn为数字,$0代表命令本身,$1-$9代表第1到第9个参数,10以上的参数需要用大括号{}包含,如${10}。$*代表命令行中所有的参数,$*把所有参数看成一个整体。$@代表命令行中所有的参数,但$@把每个参数区分对待。$#代表命令行中所有参数的个数。例如:创建一个脚本 canshu.sh:写入 echo $0 echo $1 echo $2 echo $3# 执行脚本文件:bash canshu.sh 11 22 33 #脚本名称与参数间空格分隔# canshu.sh echo 11 echo 22 echo 33# echo $0:$0 代表命令本身,$1-$9 代表第一个到第九个参数。3) 预定义变量预定义变量作用$?最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值非0(具体返回哪一个数,由命令自己决定),则证明上一个命令执行不正确。$$当前进程的进程号(PID)$!后台运行的最后一个进程的进程号(PID)cat > variable.sh#!/bin/bashecho "The current process is $$" #输出当前进程的PID#这个PID即为variable.sh脚本运行时,生成的进程PIDfind /root -name hello.sh &#使用find命令在root目录 下查找hello.sh文件echo "The last one Daemon process is $!"^Ccat variable.shbash variable.sh#The current process is 168019#The last one Daemon process is 168020#hucy 16:30:58 ~/test#find: '/root’: Permission denied4) 自定义变量用户自定义变量只在当前的Shell中生效;如果变量写入相应的配置文件,那么这个变量就会在所有的Shell中生效。输出变量的值的格式为:echo $myvar 或者 echo ${myvar}① 给变量赋值时,如果值包含空格,需要用单引号或者双引号包起来,否则会引起错误。② 给变量赋值时,如果使用单引号,那么单引号里面的变量就不会解析成真正的值;双引号则可以。③ 可以将一个命令执行的结果赋给一个变量。格式为:myvar=$(command)或者 `comand`。值得注意的是,务必要将$()和${}的用途分开。④ 变量的扩增,即将新的内容增加到变量原来的值上去。格式为"$变量名称""扩增内容" 或 ${变量}"扩增内容"。⑤ 使用export将变量变成环境变量,使得bash子进程可以使用变量。⑥ 判断变量是否未设置,如果未设置则用-后面的内容赋值。语法为:var2=${var1-hellovar1}(若var1未设置,那么将hellovar1赋值给var2,否则将var1的值赋给var2)。需要注意的是,如果var1设置为空值了,那么也算是赋值了。⑦ 判断变量是否未设置或者设置为空值,如果未设置或者设置为空值则用-后面的内容赋值。语法为:var2=${var1:-hellovar1}。更多用法与规则:

注意:给变量赋值时,注意等号两端的空格问题。(2) 参数接收键盘输入=> read [选项] [变量名]-p “提示信息” :在等待read输入时,输出提示信息-t:read命令会一直等待用户输入,使用此选项可以指定等待时间-n字符数:read命令接受指定的字符数,就会执行-s:隐藏输入的数据,适用于机密信息的输入例如:cat > stdinput.sh#!/bin/bashread -t 30 -p "Please input your name:" name#提示“请输入姓名”并等待30秒,把用户的输入保存到变量name中。echo "Name is $name"read -s -t 30 -p "Please enter your age:" age#年龄是隐私,用-s选项隐藏输入。echo "Age is $age"echo -e "\n"read -n 1 -t 30 -p "Please select your gender[M/F]:" gender#使用“-n l”选项只接收一个输入字符就会执行,不用回车echo -e "\n"echo "Sex is $gender"^C(3) 通配符wildcard是一种命令行的路径扩展(path expansion)功能。在wildcard进行扩展后, 命令行会先完成重组,才会交给shell来处理。一些常见的wildcard:wildcard功能*匹配0个或多个字符?匹配任意单一字符[list]匹配list中任意单一字符[!list]匹配不在list中任意单一字符{string1,string2,...}匹配string1或者stsring2或者(…)中其一字符串a*b # a与b之间可以有任意个字符(0个或多个),如aabcb, axyzb, a012b,ab等。a?b # a与b之间只能有一个字符,但该字符可以任意字符,如 aab, abb, acb, azb等。a[xyz]b # a与b之间只能有一个字符,但这个字符只能是x或者y或者z,如:axb, ayb, azb这三个。a[!0-9]b # a与b之间只能有一个字符,但这个字符不能是阿拉伯数字,如aab,ayb,a-b等。a{abc,xyz,123}b # a与b之间只能是abc或者xyz或者123这三个字串之一,扩展后是aabcb,axyzb,a123b。(4) 标准头文件#!/bin/bash## Author:## Address:## E-mail:## Some demo## ……set -e# Function for script description and usageusage(){cat <<EOF >&2Usage:}# 查看系统预设的shellcat /etc/shells(5) 变量替换在bash shell中, **$()**与 `` (反引号)都是用来做命令替换(command substitution)的。A=BCDA=${A}EA=ls #命令$A${A}B=la #参数C=/tmp #目录$A -$B $C #即 ls -la /tmpecho $A -$B $Cecho the last sunday is $(date -d "last sunday" +%Y-%m-%d)echo the last sunday is `date -d "last sunday" +%Y-%m-%d`(6) 循环for 变量名 in 列表; do 循环体; donewhile CONDITION; do 循环体; doneuntil CONDITION; do 循环体; done# 借助echo来确保,循环正确for i in a.txt b.txt n.txt; do echo $i; done # 文件不多,手动放在in后,用空格分开for i in `seq 1 9`; do echo SRR250${i}; done # 文件名为数字顺序,用seq命令生成连续数据,引用命令需要``for i in `ls data/*.txt`; do echo $i; done # 匹配某类文件作为输入for i in $(cat .*txt) ;do echo $i; done # 匹配某类文件作为输入for i in `cat list.txt`; do echo $i; done # 使用文本源为输入列表for i in `cat list.txt | cut -f 1`; do echo $i; done #指定某列作为输入文件名plot_heatmap.sh -i data/${i} -o heatmap/${i}.pdfls $(pwd)/SRR* | while read id;do echo $id `basename $id`;donefor id in $(ls $(pwd)/SRR*) ;do echo $id `basename $id`;done

注:basename #去除路径等,只剩基本文件名。(7) 重定向谈到 I/O redirection,不妨先认识一下File Descriptor (fd,文件描述符)。在 shell 的进程中,最常使用的 fd 有三个,分别为:0: standard Input (STDIN)1: standard output (STDOUT)2: standard Error output (STDERR)在标准情况下,这些 fd 分别跟如下设备 (device) 关联:stdin(0): keyboardstdout(1): monitorstderr(2): monitorTips: linux 中的文件描述符 (fd) 用整数表示。linux 中任何一个进程都默认打开三个文件, 这三个文件对应的文件描述符分别是:0, 1, 2; 即 stdin, stdout, stderr。用<来改变输入的数据通道 (stdin),使之从指定的文件读进。用>来改变输出的数据通道 (stdout,stderr), 使之输出到指定的文件。严格来说,<符号之前需要指定一个 fd 的 (之前不能有空白),但因为 0 是<的预设值,因此,<与0<是一样的 。标准输入:0<标准输出:1> #改变 stdout 的输出通道;标准错误:2> #改变 stderr 的输出通道;<<是所谓的here document,它可以让我们输入一段文本,直到读到<< 后指定的字符串结束。cat <<EOF>tmp.txtfirst line heresecond line herethird line hereEOF #end of file: 读到此字符串便结束,无需Ctrl+Ccat tmp.txt#first line here#second line here#third line here2>&1 #将stderr并进stdout输出。1>&2 或者 >&2 #将stdout并进stderr输出。在 linux 的文件系统中,有个设备文件: /dev/null。将 fd 1跟 fd 2重定向到 /dev/null 去,就可忽略 stdout, stderr 的输出。将 fd 0重定向到 /dev/null,那就是读进空 (nothing)。(8) 进程替换bed=exon_probe.hg38.gene.bedfor bam in ~/*.bamdo file=$(basename $bam)sample=${file%%.*}echo $sampleexport total_reads=$(samtools idxstats $bam | awk -F '\t' '{s+=$3}END{print s}')echo The number of reads is $total_readsbedtools multicov -bams $bam -bed $bed | perl -alne '{$len=$F[2]-$F[1];if($len <1) {print "$.\t$F[4]\t0"}else{$rpkm=(1000000000*$F[4]/($len*$ENV{total_reads}));print "$.\t$F[4]\t$rpkm"}}' > $sample.rpkm.txtdone注:全局变量:export%%.* #每个%表示删除一个点号及其后的字符串(右删除)。export bed=13edsfdecho $bedperl -e 'print $ENV{bed}'# https://github.com/jmzeng1314/my_WGCNA总结在bash shell中, $()与 `` (反引号)都是用来做命令替换的。$(())是用来作整数运算的。全局变量:exportbasename #去除路径等,只剩基本文件名。%%.* #每个%表示删除一个点号及其后的字符串。参考阅读:1. Linux Shell基础 - Bash变量 - 环境变量 - 位置参数变量 - 预定义变量2. 菜鸟学Linux - 变量基本规则3. Shell 十三问4. shell循环:for、while、until——详解

(0)

相关推荐