http://www.dooccn.com/shell/ (shell在线编程网站,也支持大量其他语言)
http://c.biancheng.net/shell/
http://www.runoob.com/linux/linux-shell.html
https://www.pstips.net/powershell-online-tutorials (powershell!!!)
(注意:PowerShell和bat文件没有关系;前者可以代替后者,见 https://www.cnblogs.com/ldy_ai/p/4729907.html)
本文主要研究Bourne Again Shell,即bash(/bin/bash);
(此外还有Bourne Shell即/usr/bin/sh或/bin/sh、C Shell即/usr/bin/csh、K Shell即/usr/bin/ksh等;)
(cat /etc/shells可以查看所有shell!!!)
(查看shell版本:echo $BASH_VERSION或bash --version)
若sh文件中第一行写了#!/bin/bash,则直接./test.sh即可;
若没写,可以执行 /bin/sh test.sh;
echo $your_name和echo ${your_name}等价;
要想变量的作用域仅限于函数内部,可在定义时加上local命令,此时变量就是局部变量;(shell和js类似, 函数内部定义的变量,默认是全局变量;js需要加var才能变为局部变量;)
readonly XXX可以声明变量为只读;
unset XXX可以删除变量;(注意:它不能删除只读变量)
(declare -r n=10也可以声明变量为只读)
shell的字符串可以是单引号、双引号或无引号,区别是单引号无法定义变量;
(具体情况较为复杂和迷惑,总之双引号比单引号好;)
echo ${#string}#获取字符串长度
echo ${string:1:4}#截取子串
echo ${string:0-1:4}#表示从右边开始截取
#查找子串(字符i或o的位置,哪个先出现就计算哪个)
string=“runoob is a great site”
echo expr index "$string" io
# 输出 4
#shell数组
array_name=(value0 value1 value2 value3)
或array_name[0]=value0单独赋值;
甚至ages=([3]=24 [5]=19 [10]=12),即无需挨个赋值,类型也可以不同;
注意:数组读取必须加大括号,如echo ${array_name[1]}
获取全部元素,执行echo ${array_name[@]}
获取数组长度,执行echo ${#array_name[@]}或echo ${#array_name[*]}
获取某个元素的长度,执行echo ${#array_name[n]}
echo {1…10}
time echo {1…100}
for a in {1…10};do echo $ a; done;
aNumList=$(seq 100); echo $aNumList
shell的单行注释和python一样;
shell的多行注释为:
:<<EOF (其中’:'可以去掉)
注释内容…
EOF (其中’EOF’也可以用别的符号,如单引号、感叹号、或任意字符串)
shell中捕捉传递的参数方式$0、$1、$2、$3…;
捕捉参数个数方式 $ #;
以单字符串捕捉所有参数方式$ *;
(此外还有$ $、 $ !、 $ @、 $ -、 $ ?等;其中 $ @和 $ *比较类似;
$ !和 $ $ 都与进程id有关; $?和退出状态有关;)
shell利用expr等工具实现简单的数学运算,如:
val=expr 2 + 2
echo “两数之和为 : $ val”
注意:2 + 2之间必须有空格;
(除了expr,还有bc、let、awk也可用于数值计算;其中bc和awk可以浮点运算;)
(也可以直接用((a=3+5, b=a+10)) echo $ a $b;c= $ ((4+8, a+b)) echo $ c;注意:以最后一个表达式的结果作为整个(())命令的执行结果 )
(也可以使用echo $[3*5];注意不能没有echo!)
(bc非常强大,是一个任意精度的计算器语言;)
(注意:非数值类,比如字符串,千万不能用let!!!)
算术运算符:
expr $a + $b
、expr $a - $b
、expr $a \* $b
、expr $b / $a
、expr $b % $a
、a=$b、[ $a == $b ]、 [ $ a != $ b ]
(乘法比较特别,需要转义;除法是整数之间的除法;)
注意: [ $a == $b ]必须有有空格;
用gawk或awk实现小数除法:
aa=11.1
bb=23.0
gawk -v x= $ aa -v y= $ bb ‘BEGIN{printf “%.3f\n”,x+y}’
#bc的demo1:
a=7.2
b=8
if [ echo "$a < $b"|bc
-eq 1 ]
then
echo "$a < $b "
else
echo " $ a > $ b "
fi
#bc的demo2:
for((i=1;i<=10;i++))
do
echo $ i
j= $ (echo “$i*0.2-2.5”|bc)
echo $ j
done
关系运算符:
[ $a -eq $b ]、[ $a -ne $b ]、[ $a -gt $b ]、[ $a -lt $b ]、[ $a -ge $b ]、[ $a -le $b ]
(注意:只支持数字,不支持字符串)
布尔运算符:
[ ! false ]、[ $a -lt 20 -o $b -gt 100 ]、[ $a -lt 20 -a $b -gt 100 ]
逻辑运算符:
[[ $a -lt 100 && $b -gt 100 ]]、[[ $a -lt 100 || $b -gt 100 ]]
(逻辑运算符和布尔运算符啥区别?都是将多个表达式连在一起判断,难道只有两层括号的区别?)
(逻辑运算符是对test命令和布尔运算符的改进?去掉-o和-a,只能使用 || 和 &&;)
(推荐使用逻辑运算符即[[]] !!!)
([[ ]]对数字的比较不友好,建议使用if判断条件时,用(())处理整型数字,用[[ ]]处理字符串或者文件;)
字符串运算符:
[ $a = $b ]、[ $a != $b ]、[ -z
a
]
、
[
−
n
"
a ]、[ -n "
a]、[−n"a" ]、[ $a ]
文件测试运算符:
[ -b $file ]、[ -c $file ]、[ -d $file ]、[ -f $file ]、[ -g $file ]、[ -k $file ]、[ -p $file ]、
[ -u $file ]、[ -r $file ]、[ -w $file ]、[ -x $file ]、[ -s $file ]、[ -e $file ]
#从标准输入读取一个变量
read name
echo “$name It is a test”
printf和echo类似,但它不会自动加\n,它还能设定对齐、宽度等;
如printf “%-10s %-8s %-4.2f\n” 郭靖 男 66.1234
test命令可以对数值、字符和文件3方面进行测试;
(注意:它和关系运算符类似,不过它不加括号;如if test $[num1] -eq $[num2]和[ $a -eq $b ]对比)
(数值:-eq、-ne、-gt、-ge、-lt、-le;字符串:=、!=、-z、-n ;文件:-e、-f、-w、-x、-s、-d、-f、-c、-b)
##############
#shell打印一个目录的文件名
for file in ls /etc
do
echo $file
done
#for循环一种写法
for((i=1;i<=5;i++ ))
do
echo “这是第 $i 次调用”;
done
可以不加分号(done和for后面),但一定要加两层括号,且中间不能有空格;
shell虽然很灵活(比如没有python那样的对齐),但它有自己的坚持!!!
#for循环第二种写法
num1= $ [2*3]
num2= $ [1+5]
if test $[num1] -eq $[num2]
then
echo ‘两个数字相等!’
else
echo ‘两个数字不相等!’
fi
#for循环第三种写法
for loop in 1 2 3 4 5
do
echo “The value is: $loop”
done
#while循环
int=1
while(( $int<=5 ))
do
echo $int
let “int++”
done
#while无限循环
while : (或while true、for (( ; ; )) )
do
command
done
#until 循环
(until循环与while循环在处理方式上刚好相反;)
until condition
do
command
done
case in语句类似switch case,末尾要加esac,这点和if类似;
read aNum
case $aNum in
1 ) echo ‘你选择了 1’
;;
2 ) echo ‘你选择了 2’
;;
* ) echo ‘你没有输入 1 到 2 之间的数字’
;;
esac
shell的break和continue与其他语言相同;
shell的函数定义不用写def,调用不用加括号;
(参数不用写在函数括号中,直接用 $ 1、 $ n、$#等捕捉即可;)
Shell输入输出重定向:
n >& m#将输出文件 m 和 n 合并
n <& m#将输入文件 m 和 n 合并
(0是标准输入STDIN、1是标准输出STDOUT、2是标准错误输出STDERR)
(每个 Unix/Linux 命令运行时都会打开三个文件,STDIN、STDOUT和STDERR;文件描述符分别为0、1、2;)
(Unix程序默认从stdin读取数据、向stdout输出数据、向stderr流中写入错误信息;)
注意:cat words.txt | while read line使用的管道,会导致创建subshell,从而导致循环内的map无法赋值给循环外的map;
可以使用while read line 。。done < words.txt代替;
(https://blog.youkuaiyun.com/ystyaoshengting/article/details/83240678 刷Leecode192也遇到相同的问题)
sort命令:
sort tmp.txt -t " " -k 2 -r
(文件每行有key value代表word及count,按照value逆序打印,分隔符为空格,以第二列作为key)
https://blog.youkuaiyun.com/monkeyduck/article/details/10097829