@wanghuijiao
2021-04-01T16:55:38.000000Z
字数 5953
阅读 609
学习笔记
<something>
的字串,可以替换成自己需要的值。比如可以替换成具体的文件名/tmp/1.txt
出现[something]
时,表示这一项是可选的、可以省略的。
$ a="value"
$ echo ${a}
value
# 常用操作,不能省{}的情况
$ cp $a ${a}_backup
# 内嵌在字符串中,双引号展开变量,对变量进行解释
$ echo "${a} is cool"
value is cool
# 单引号原样输出
$ echo '${a} is cool'
${a} is cool
# "\"是使特殊字符保持原样,"\$"会使得"$"仅作为普通字符,"$a"不再被替换
$ echo "\$a is cool"
$a is cool
$ echo '\$a is cool'
\$a is cool
$PATH
,表示搜索可执行文件的路径列表。(有点不懂,需要稍后自行查询)。用env
查询当前系统里的所有内置变量。$1,$2...
得到命令行输入参数,$0
是脚本本身。
$ cat watch-arguments.sh
#!/bin/bash
echo "script file name : $0"
echo "first argument : $1"
echo "second argument : $2"
$ ./watch-arguments.sh good job
script file name : ./watch-arguments.sh
first argument : good
second argument : job
CUDA_VISIBLE_DEVICES
该变量的值,来确定使用哪些GPU。
$ CUDA_VISIBLE_DEVICES='0,1' python train.py
export
: 用export赋值的变量,子进程可见. 因此设置环境变量有两种方式,一种是命令前同一行直接赋值, 另一种是用export赋值. 区别是后者在本shell的生命周期内都有影响.
$ python -c 'import os; import sys;print os.environ.get(sys.argv[1])' some_var
# 直接在shell中赋值的变量,子进程不可见
None
$ some_var=kk python -c 'import os; import sys;print os.environ.get(sys.argv[1])' some_var
#直接在子进程运行前赋值的变量,是可见的.
$ echo $some_var
# 上一行中的单行赋值方式不会"污染"全局环境, 仅对后面接的命令有效.
(输出为空)
$ export some_var='kk'
$ echo $some_var
kk
$ python -c 'import os; import sys;print os.environ.get(sys.argv[1])' some_var
kk
$ echo 'k1=v1' > vars.sh
$ chmod +x ./vars.sh
$ ./vars.sh
$ echo $k1 # 什么都没有输出来。原因是刚才 'k1=v1' 在一个独立的sh脚本运行时,会在新开的子shell中运行,子shell运行结束后,其中的变量(k1)也不复存在。因此子shell中的这句赋值不会对父shell有任何影响。
$ source ./vars.sh
$ echo $k1 # 这一次赋值的效果出现在了父shell中。原因是 source 后的脚本,不再是新开子shell运行,source使得 vars.sh 中的每一行,像在父shell中执行一样。本例中,就是 k1=v1 在父shell中运行了。
v1
$()
或``,将$()的输出结果赋值给另一个变量
$ ret=$(cat readme.txt)
$ echo $ret
Working in 837 is a lot of fun.
$ ret=`cat readme.txt`
$ echo $ret
Working in 837 is a lot of fun.
$ let "a=5+6"
$ echo $a
11
$ x=5
$ y=6
$ let "z=x*y"
$ echo $z
30
$ expr 5 + 6
11
$ foo=$(expr 5 + 6)
$ echo $foo
11
$ a=$((5+6))
$ echo $a
11
if <condition>
then
<cmd>
else
<cmd>
fi
else语句可以省略。比如:
#!/bin/bash
tmp=35
# -ge great or equal
if [ ${tmp} -ge 30]
then
echo "It's hot, we should turn on the AC."
else
fi
# 其中-e用来判断文件是否存在。
if [ -e /bin/ls ]
then
echo "Your 'ls' binary is on the usual path."
else
echo "I can't find the 'ls' binary."
fi
# 比较大小
$ test 5 -ge 4
$ echo $?
0
# 其中$?是上一个命令的返回结果。Test命令的返回结果,0表示结果是True或者命令运行成功;1表示结果是False或者命令运行不成功
code_review="pass"
regression_test="pass"
if [ $code_review = "pass" ] && [ $regression_test = "pass" ]
then
echo "ship it!"
fi
$ for var in <list>
do
<command>
done
# 示例
$ cat test-loop.sh
#!/bin/bash
for x in 830 837 846 859
do
echo "Our teams are in room ${x}."
done
echo {1..3}
for i in {1..3}
do
echo "I got ${i} tickets."
done
# 输出
1 2 3
I got 1 tickets.
I got 2 tickets.
I got 3 tickets.
for ((i=1; i<=3; i++))
do
echo "I fixed ${i} bugs."
done
# 输出
I fixed 1 bugs.
I fixed 2 bugs.
I fixed 3 bugs.
until [ <some test> ]
do
<commands>
done
i++
bash支持自加写法
suffix=1
until [ ! -e "foo${suffix}" ]
do
let suffix++
done
echo "The file name foo${suffix} is good."
# 发现第一个有鱼的餐厅,打印并退出
for res in YUYU LanZhouLaMian ShaoFen fish
do
# -q 表示不显示,在${res}.txt文件中查找fish字符
grep -q fish ${res}.txt
# $?用来获取上一条命令的返回值
found=$?
if [ $found = 0 ]
then
echo "We have fish from $res!"
break
fi
done
# 跳过所有含辣的餐馆
for res in YUYU LanZhouLaMian ShaoFen fish
do
grep -q spicy ${res}.txt
found=$?
if [ $found = 0 ]
then
continue
fi
done
function_name (){
<commands>
}
# 或者
function function_name{
<commands>
}
调用时,直接调用function_name即可。必须在调用前定义函数。
# 下面的函数打印系统信息:
print_distro_info() {
echo "Here is the distro info:"
uname -a
}
print_distro_info
函数也可以有参数,用\$1,$2
得到,例如:
discuss_languages(){
languages1=$1
languages2=$2
echo "$1 is a good language."
echo "$2 is also a good language."
}
discuss_languages c++ python
注意调用时,参数两边没有括号
find_cpp_files(){
local folder=$1
local ret=$(find ${folder} -name '*.cpp' | wc -l)
return $ret
}
folder=/ssd01/wanghuijiao
find_cpp_files $folder
num_files=$?
echo "There are ${num_files} cpp files in ${folder}"
#!/bin/bash
# Experimenting with variable scope
var_change(){
local var1='local 1'
echo "Inside function: var1=\"$var1\" var2=\"$var2\""
var1='change again'
var2='2 changed again'
}
var1='global 1'
var2='global 2'
echo "Before function call: var1=\"$var1\" var2=\"$var2\""
var_change
echo "After function call: var1=\"$var\" var2=\"$var2""
#!/bin/bash
set -e
mkdir ./tmp/data
echo "Directory ./tmp/data was just created."
# 输出
mkdir:./tmp/data: File exists
#!/bin/bash
set -x
floor=8th
echo "A lot of power has been consumed at the ${floor} floor."
# 输出
+ floor=8ths
+ echo 'A lot of power has been consumed at the 8th floor.'
A lot of power has been consumed at the 8th floor.
注意:实际调试可以用bash -x或bash -e的方式来运行脚本,来达到set -x或者set -e 的效果。这样的好处时不需要改脚本。
find . -name "*.py" | wc -l
printf '#!/bin/bash\ngrep "processor|model name" /proc/cpuinfo\n' > /tmp/1.sh
touch testfile
# 修改文件时间属性为当前系统时间,若testflie不存在则创建新的testfile空白文件ls -l testfile
# 查看文件时间属性