各种循环数组写法
#!/bin/bash
my_arry=(a b "c","d" abc)
echo "-------FOR循环遍历输出数组--------"
for i in ${my_arry[@]};
do
echo $i
done
echo "-------::::WHILE循环输出 使用 let i++ 自增:::::---------"
j=0
while [ $j -lt ${#my_arry[@]} ]
do
echo ${my_arry[$j]}
let j++
done
echo "--------:::WHILE循环输出 使用 let "n++ "自增: 多了双引号,其实不用也可以:::---------"
n=0
while [ $n -lt ${#my_arry[@]} ]
do
echo ${my_arry[$n]}
let "n++"
done
echo "---------::::WHILE循环输出 使用 let m+=1 自增,这种写法其他编程中也常用::::----------"
m=0
while [ $m -lt ${#my_arry[@]} ]
do
echo ${my_arry[$m]}
let m+=1
done
echo "-------::WHILE循环输出 使用 a=$[$a+1] 自增,个人觉得这种写法比较麻烦::::----------"
a=0
while [ $a -lt ${#my_arry[@]} ]
do
echo ${my_arry[$a]}
a=$[$a+1]
doneseq 命令
如果 for 循环是按 1 递增的,可以利用 seq 命令来生成数字系列,参考写法如下:
#!/bin/bash
max=5
for index in `seq $max`
do
echo $index
doneMIT

在条件语句中,我们比较 $? 是否等于0。 Bash实现了许多类似的比较操作,您可以查看 test 手册。 在bash中进行比较时,尽量使用双方括号 [[ ]] 而不是单方括号 [ ],这样会降低犯错的几率,尽管这样并不能兼容 sh。 更详细的说明参见这里。
这里 $1 是脚本的第一个参数。与其他脚本语言不同的是,bash 使用了很多特殊的变量来表示参数、错误代码和相关变量。下面是列举来其中一些变量,更完整的列表可以参考 这里。
$参数
-
$0- 脚本名 -
$1到$9- 脚本的参数。$1是第一个参数,依此类推。 -
$@- 所有参数 -
$#- 参数个数 -
$?- 前一个命令的返回值 -
$$- 当前脚本的进程识别码 -
!!- 完整的上一条命令,包括参数。常见应用:当你因为权限不足执行命令失败时,可以使用sudo !!再尝试一次。 -
$_- 上一条命令的最后一个参数。如果你正在使用的是交互式 shell,你可以通过按下Esc之后键入 . 来获取这个值 -
通配符 - 当你想要利用通配符进行匹配时,你可以分别使用
?和*来匹配一个或任意个字符。例如,对于文件foo,foo1,foo2,foo10和bar,rm foo?这条命令会删除foo1和foo2,而rm foo*则会删除除了bar之外的所有文件。 -
花括号
{}- 当你有一系列的指令,其中包含一段公共子串时,可以用花括号来自动展开这些命令。这在批量移动或转换文件时非常方便。
convert image.{png,jpg}
# 会展开为
convert image.png image.jpg
cp /path/to/project/{foo,bar,baz}.sh /newpath
# 会展开为
cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath
# 也可以结合通配使用
mv *{.py,.sh} folder
# 会移动所有 *.py 和 *.sh 文件
mkdir foo bar
# 下面命令会创建foo/a, foo/b, ... foo/h, bar/a, bar/b, ... bar/h这些文件
touch {foo,bar}/{a..h}
touch foo/x bar/y
# 比较文件夹 foo 和 bar 中包含文件的不同
diff <(ls foo) <(ls bar)
# 输出
# < x
# ---
# > y编写 bash 脚本有时候会很别扭和反直觉。例如 shellcheck 这样的工具可以帮助你定位 sh/bash 脚本中的错误。
shellcheck mcd.sh
查找代码
grep 有很多选项,这也使它成为一个非常全能的工具。其中我经常使用的有 -C :获取查找结果的上下文(Context);-v 将对结果进行反选(Invert),也就是输出不匹配的结果。举例来说, grep -C 5 会输出匹配结果前后五行。当需要搜索大量文件的时候,使用 -R 会递归地进入子目录并搜索所有的文本文件。
但是,我们有很多办法可以对 grep -R 进行改进,例如使其忽略.git 文件夹,使用多CPU等等。
因此也出现了很多它的替代品,包括 ack, ag 和 rg。它们都特别好用,但是功能也都差不多,我比较常用的是 ripgrep (rg) ,因为它速度快,而且用法非常符合直觉。例子如下:
# 查找所有使用了 requests 库的文件
rg -t py 'import requests'
# 查找所有没有写 shebang 的文件(包含隐藏文件)
rg -u --files-without-match "^#!"
# 查找所有的foo字符串,并打印其之后的5行
rg foo -A 5
# 打印匹配的统计信息(匹配的行和文件的数量)
rg --stats PATTERN查找 shell 命令
目前为止,我们已经学习了如何查找文件和代码,但随着你使用shell的时间越来越久,您可能想要找到之前输入过的某条命令。首先,按向上的方向键会显示你使用过的上一条命令,继续按上键则会遍历整个历史记录。
history 命令允许您以程序员的方式来访问 shell 中输入的历史命令。这个命令会在标准输出中打印 shell 中的里面命令。如果我们要搜索历史记录,则可以利用管道将输出结果传递给 grep 进行模式搜索。 history | grep find 会打印包含 find 子串的命令。
对于大多数的 shell 来说,您可以使用 Ctrl+R 对命令历史记录进行回溯搜索。敲 Ctrl+R 后您可以输入子串来进行匹配,查找历史命令行。
反复按下就会在所有搜索结果中循环。在 zsh 中,使用方向键上或下也可以完成这项工作。
Ctrl+R 可以配合 fzf 使用。fzf 是一个通用对模糊查找工具,它可以和很多命令一起使用。这里我们可以对历史命令进行模糊查找并将结果以赏心悦目的格式输出。
另外一个和历史命令相关的技巧我喜欢称之为基于历史的自动补全。 这一特性最初是由 fish shell 创建的,它可以根据您最近使用过的开头相同的命令,动态地对当前对shell命令进行补全。这一功能在 zsh 中也可以使用,它可以极大的提高用户体验。
你可以修改 shell history 的行为,例如,如果在命令的开头加上一个空格,它就不会被加进shell记录中。当你输入包含密码或是其他敏感信息的命令时会用到这一特性。 为此你需要在.bashrc中添加HISTCONTROL=ignorespace或者向.zshrc 添加 setopt HIST_IGNORE_SPACE。 如果你不小心忘了在前面加空格,可以通过编辑。bash_history或 .zhistory 来手动地从历史记录中移除那一项。
文件夹导航
之前对所有操作我们都默认一个前提,即您已经位于想要执行命令的目录下,但是如何才能高效地在目录 间随意切换呢?有很多简便的方法可以做到,比如设置alias,使用 ln -s 创建符号连接等。而开发者们已经想到了很多更为精妙的解决方案。
由于本课程的目的是尽可能对你的日常习惯进行优化。因此,我们可以使用fasd和 autojump 这两个工具来查找最常用或最近使用的文件和目录。
Fasd 基于 frecency 对文件和文件排序,也就是说它会同时针对频率(frequency)和时效(recency)进行排序。默认情况下,fasd使用命令 z 帮助我们快速切换到最常访问的目录。例如, 如果您经常访问/home/user/files/cool_project 目录,那么可以直接使用 z cool 跳转到该目录。对于 autojump,则使用j cool代替即可。
还有一些更复杂的工具可以用来概览目录结构,例如 tree, broot 或更加完整的文件管理器,例如 nnn 或 ranger。
作业
对于大多数的 shell 来说,您可以使用 Ctrl+R 对命令历史记录进行回溯搜索。敲 Ctrl+R 后您可以输入子串来进行匹配,查找历史命令行。
反复按下就会在所有搜索结果中循环。在 zsh 中,使用方向键上或下也可以完成这项工作。
Ctrl+R 可以配合 fzf 使用。fzf 是一个通用对模糊查找工具,它可以和很多命令一起使用。这里我们可以对历史命令进行模糊查找并将结果以赏心悦目的格式输出。
另外一个和历史命令相关的技巧我喜欢称之为基于历史的自动补全。 这一特性最初是由 fish shell 创建的,它可以根据您最近使用过的开头相同的命令,动态地对当前对shell命令进行补全。这一功能在 zsh 中也可以使用,它可以极大的提高用户体验。
你可以修改 shell history 的行为,例如,如果在命令的开头加上一个空格,它就不会被加进shell记录中。当你输入包含密码或是其他敏感信息的命令时会用到这一特性。 为此你需要在.bashrc中添加HISTCONTROL=ignorespace或者向.zshrc 添加 setopt HIST_IGNORE_SPACE。 如果你不小心忘了在前面加空格,可以通过编辑。bash_history或 .zhistory 来手动地从历史记录中移除那一项。
文件夹导航
之前对所有操作我们都默认一个前提,即您已经位于想要执行命令的目录下,但是如何才能高效地在目录 间随意切换呢?有很多简便的方法可以做到,比如设置alias,使用 ln -s 创建符号连接等。而开发者们已经想到了很多更为精妙的解决方案。
由于本课程的目的是尽可能对你的日常习惯进行优化。因此,我们可以使用fasd和 autojump 这两个工具来查找最常用或最近使用的文件和目录。
Fasd 基于 frecency 对文件和文件排序,也就是说它会同时针对频率(frequency)和时效(recency)进行排序。默认情况下,fasd使用命令 z 帮助我们快速切换到最常访问的目录。例如, 如果您经常访问/home/user/files/cool_project 目录,那么可以直接使用 z cool 跳转到该目录。对于 autojump,则使用j cool代替即可。
还有一些更复杂的工具可以用来概览目录结构,例如 tree, broot 或更加完整的文件管理器,例如 nnn 或 ranger。