筆記接上篇【Linux 筆記】Linux 基本操作 - 01. 系統(tǒng)認知-文本處理-軟件安裝-環(huán)境變量,。筆記大部分源于生信技能樹的B站視頻教程【生信技能樹】生信人應該這樣學linux(更新至第14集),,如有需要,,可去欣賞原汁原味的視頻講解,。
8. shell編程基礎(1) 變量1) 環(huán)境變量 環(huán)境變量會在當前Shell和這個Shell的所有子Shell當中生效,。 ① 設置全局環(huán)境變量:export 變量名=變量值 ② 查看環(huán)境變量:env ③ 查看變量內容:echo $變量名 ④ 刪除變量: unset 變量名 ⑤ 常見系統(tǒng)預定義環(huán)境變量:HOME 、PWD ,、PATH ,、PS1 echo $HOME #顯示主目錄 echo $PWD #顯示當前工作目錄 echo $PATH #顯示系統(tǒng)查找命令的路徑 echo $PS1 #顯示已設置的系統(tǒng)提示符變量 # \[\e[32;1m\]\u \[\e[33;1m\]\t \[\e[35;1m\]\w \n\[\e[0;40m\]$
PS1:
變量 | 說明 |
---|
\d | 顯示日期,格式為 “星期 月 日” | \h | 顯示簡寫主機名,。如,,默認主機名 “l(fā)ocalhost” | \t | 顯示24小時制時間,,格式為 “HH:MM:SS” | \T | 顯示12小時制時間,格式為 “HH:MM:SS” | \A | 顯示24小時制時間,,格式為 “HH:MM” | \u | 顯示當前用戶名 | \w | 顯示當前用戶所在目錄的完整名稱 | \W | 顯示當前所在目錄的最后一個目錄 | # | 執(zhí)行的第幾個命令 | $ | 提示符,。如果是root用戶會顯示提示符為 “#”,如果是普通用戶則會顯示提示符為“$”,。 |
例如:[root@bogon ~]# PS1="[\u@\t \w]$ " :\u:代表root,;\t代表24小時制時間;\w(w小寫表示絕對路徑),。 2) 位置參數(shù)變量→寫入到腳本文件內 echo $12 #"$1"為變量,,"2"為一個字符串,;故,,"$12"輸出為"$1"的內容加上字符串2 echo ${12} #變量"$12"
位置參數(shù)變量 | 作用 |
---|
$n | n為數(shù)字,$0 代表命令本身,,$1-$9 代表第1到第9個參數(shù),,10以上的參數(shù)需要用大括號{} 包含,,如${10} 。 | $* | 代表命令行中所有的參數(shù),,$* 把所有參數(shù)看成一個整體,。 | $@ | 代表命令行中所有的參數(shù),但$@ 把每個參數(shù)區(qū)分對待,。 | $# | 代表命令行中所有參數(shù)的個數(shù),。 |
例如:創(chuàng)建一個腳本 canshu.sh:寫入 echo $0 echo $1 echo $2 echo $3 # 執(zhí)行腳本文件: bash canshu.sh 11 22 33 #腳本名稱與參數(shù)間空格分隔 # canshu.sh echo 11 echo 22 echo 33 # echo $0:$0 代表命令本身,$1-$9 代表第一個到第九個參數(shù),。
3) 預定義變量 預定義變量 | 作用 |
---|
$? | 最后一次執(zhí)行的命令的返回狀態(tài),。如果這個變量的值為0,證明上一個命令正確執(zhí)行,;如果這個變量的值非0(具體返回哪一個數(shù),由命令自己決定),,則證明上一個命令執(zhí)行不正確,。 | $$ | 當前進程的進程號(PID) | $! | 后臺運行的最后一個進程的進程號(PID) |
cat > variable.sh #!/bin/bash echo "The current process is $$" #輸出當前進程的PID #這個PID即為variable.sh腳本運行時,生成的進程PID
find /root -name hello.sh & #使用find命令在root目錄 下查找hello.sh文件 echo "The last one Daemon process is $!" ^C
cat variable.sh
bash variable.sh #The current process is 168019 #The last one Daemon process is 168020 #hucy 16:30:58 ~/test #find: '/root’: Permission denied
4) 自定義變量 用戶自定義變量只在當前的Shell中生效,;如果變量寫入相應的配置文件,,那么這個變量就會在所有的Shell中生效。 輸出變量的值的格式為:echo $myvar 或者 echo ${myvar} ① 給變量賦值時,,如果值包含空格,,需要用單引號或者雙引號包起來,否則會引起錯誤。 ② 給變量賦值時,,如果使用單引號,,那么單引號里面的變量就不會解析成真正的值;雙引號則可以,。 ③ 可以將一個命令執(zhí)行的結果賦給一個變量,。格式為:myvar=$(command) 或者 `comand`。值得注意的是,,務必要將$() 和${} 的用途分開,。 ④ 變量的擴增,即將新的內容增加到變量原來的值上去,。格式為"$變量名稱""擴增內容" 或 ${變量}"擴增內容" ,。 ⑤ 使用export將變量變成環(huán)境變量,使得bash子進程可以使用變量,。 ⑥ 判斷變量是否未設置,,如果未設置則用-后面的內容賦值。語法為:var2=${var1-hellovar1} (若var1 未設置,,那么將hellovar1 賦值給var2 ,,否則將var1 的值賦給var2 )。需要注意的是,,如果var1 設置為空值了,,那么也算是賦值了,。 ⑦ 判斷變量是否未設置或者設置為空值,,如果未設置或者設置為空值則用-后面的內容賦值。語法為:var2=${var1:-hellovar1} ,。 更多用法與規(guī)則:
注意:給變量賦值時,,注意等號兩端的空格問題。 (2) 參數(shù)接收鍵盤輸入=> read [選項] [變量名] -p “提示信息” :在等待read輸入時,,輸出提示信息
-t :read命令會一直等待用戶輸入,,使用此選項可以指定等待時間
-n 字符數(shù):read命令接受指定的字符數(shù),就會執(zhí)行
-s :隱藏輸入的數(shù)據(jù),,適用于機密信息的輸入
例如: cat > stdinput.sh #!/bin/bash read -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”選項只接收一個輸入字符就會執(zhí)行,不用回車 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之間只能有一個字符,但這個字符不能是阿拉伯數(shù)字,,如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 usage usage() { cat <<EOF >&2 Usage: }
# 查看系統(tǒng)預設的shell cat /etc/shells
(5) 變量替換在bash shell中, **$()**與 `` (反引號)都是用來做命令替換(command substitution)的。 A=BCD A=${A}E
A=ls #命令 $A ${A}
B=la #參數(shù) C=/tmp #目錄
$A -$B $C #即 ls -la /tmp echo $A -$B $C
echo the last sunday is $(date -d "last sunday" +%Y-%m-%d) echo the last sunday is `date -d "last sunday" +%Y-%m-%d`
(6) 循環(huán)for 變量名 in 列表; do 循環(huán)體; done
while CONDITION; do 循環(huán)體; done
until CONDITION; do 循環(huán)體; done
# 借助echo來確保,,循環(huán)正確 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 # 文件名為數(shù)字順序,,用seq命令生成連續(xù)數(shù)據(jù),,引用命令需要`` 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}.pdf
ls $(pwd)/SRR* | while read id;do echo $id `basename $id`;done for 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) 關聯(lián): stdin(0): keyboard stdout(1): monitor stderr(2): monitor
Tips: linux 中的文件描述符 (fd) 用整數(shù)表示。linux 中任何一個進程都默認打開三個文件, 這三個文件對應的文件描述符分別是:0, 1, 2; 即 stdin, stdout, stderr,。 用< 來改變輸入的數(shù)據(jù)通道 (stdin),,使之從指定的文件讀進。用> 來改變輸出的數(shù)據(jù)通道 (stdout,,stderr), 使之輸出到指定的文件,。嚴格來說,<符號之前需要指定一個 fd 的 (之前不能有空白),但因為 0 是<的預設值,,因此,,< 與0< 是一樣的 。 標準輸入:0< 標準輸出:1> #改變 stdout 的輸出通道,; 標準錯誤:2> #改變 stderr 的輸出通道,;
<< 是所謂的here document,它可以讓我們輸入一段文本,,直到讀到<< 后指定的字符串結束,。
cat <<EOF>tmp.txt first line here second line here third line here EOF #end of file: 讀到此字符串便結束,無需Ctrl+C
cat tmp.txt #first line here #second line here #third line here
2>&1 #將stderr并進stdout輸出,。
1>&2 或者 >&2 #將stdout并進stderr輸出,。 在 linux 的文件系統(tǒng)中,有個設備文件: /dev/null ,。將 fd 1跟 fd 2重定向到 /dev/null 去,,就可忽略 stdout, stderr 的輸出。將 fd 0重定向到 /dev/null,,那就是讀進空 (nothing),。
(8) 進程替換bed=exon_probe.hg38.gene.bed for bam in ~/*.bam do file=$(basename $bam) sample=${file%%.*} echo $sample export total_reads=$(samtools idxstats $bam | awk -F '\t' '{s+=$3}END{print s}') echo The number of reads is $total_reads bedtools 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.txt done
注: 全局變量:export %%.* #每個%表示刪除一個點號及其后的字符串(右刪除)。 export bed=13edsfd echo $bed perl -e 'print $ENV{bed}' # https://github.com/jmzeng1314/my_WGCNA
總結在bash shell中, $()與 `` (反引號)都是用來做命令替換的,。 $(())是用來作整數(shù)運算的,。 全局變量:export basename #去除路徑等,只?;疚募?。 %%.* #每個%表示刪除一個點號及其后的字符串。
參考閱讀: 1. Linux Shell基礎 - Bash變量 - 環(huán)境變量 - 位置參數(shù)變量 - 預定義變量 2. 菜鳥學Linux - 變量基本規(guī)則 3. Shell 十三問 4. shell循環(huán):for,、while,、until——詳解
|