The Missing Semester - 第二讲 学习笔记
第二讲 Shell 工具和脚本
课程视频地址:
https://www.bilibili.com/video/BV1Vv411v7FR
本机学习使用平台:虚拟机ubuntu18.04.6
主题一:Shell脚本
我们已经学习来如何在 shell 中执行命令,并使用管道将命令组合使用。但是,很多情况下我们需要执行一系列的操作并使用条件或循环这样的控制流。这时就要使用shell脚本。
赋值语句
#注意赋值时不能有空格,空格是用于分隔参数的保留字符
grapefruitcat@grapefruitcat:~$ foo=bar
grapefruitcat@grapefruitcat:~$ echo $foo
bar
# not 'foo = bar', 这会变成引用foo命令
原义字符串和转义字符串
对于纯字符串,'和"是等价的,例如
grapefruitcat@grapefruitcat:~$ echo 'hello'
hello
grapefruitcat@grapefruitcat:~$ echo "hello"
hello
但对于某些字符,'是作为原义字符串,不会对引号内的串进行语义转换;
而"是转义字符串,会将引号内的变量值展开(替换)。如:
grapefruitcat@grapefruitcat:~$ echo 'Value is $foo'
Value is $foo
grapefruitcat@grapefruitcat:~$ echo "Value is $foo"
Value is bar
这也是第一讲课后习题中使用echo命令输入字符串到文件时要将"转换为'使用的原因。
控制流关键字和函数
bash支持if, case, while 和 for 这些控制流关键字。
bash也可以像其它的编程语言一样写出可以接受参数的函数:
#接受一个参数,按照参数名称在当前目录下创建同名文件夹,并cd到这个文件夹
grapefruitcat@grapefruitcat:~$ mcd () {
> mkdir -p "$1"
> cd "$1"
> }
grapefruitcat@grapefruitcat:~$ mcd kksk
grapefruitcat@grapefruitcat:~/kksk$
函数中的$变量对应的表示:
$0- 脚本名$1到$9- 脚本的参数。$1是第一个参数,依此类推。$@- 所有参数$#- 参数个数$?- 前一个命令的返回值$$- 当前脚本的进程识别码!!- 完整的上一条命令,包括参数。常见应用:当你因为权限不足执行命令失败时,可以使用sudo !!再尝试一次。$_- 上一条命令的最后一个参数。如果你正在使用的是交互式 shell,你可以通过按下Esc之后键入.来获取这个值。
我们将函数直接键入shell中它就会起作用,实际上把它写进文件中会更好。shell脚本文件后缀为sh。
#写入shell脚本
grapefruitcat@grapefruitcat:~$ vim test2.sh
grapefruitcat@grapefruitcat:~$ cat test2.sh
kksk () {
mkdir -p "$1"
cd "$1"
}
#脚本未运行,函数kksk未定义
grapefruitcat@grapefruitcat:~$ kksk ppp
kksk:未找到命令
#使用source命令运行脚本
grapefruitcat@grapefruitcat:~$ source test2.sh
grapefruitcat@grapefruitcat:~$ kksk ppp
grapefruitcat@grapefruitcat:~/ppp$
命令的返回值
命令通常使用
STDOUT来返回输出值,使用STDERR来返回错误及错误码,便于脚本以更加友好的方式报告错误。 返回码或退出状态是脚本/命令之间交流执行状态的方式。返回值0表示正常执行,其他所有非0的返回值都表示有错误发生。
错误码(或者退出码、返回码) error code 的理解应该为返回值会更为准确。
#未发生错误
grapefruitcat@grapefruitcat:~$ echo "hello"
hello
grapefruitcat@grapefruitcat:~$ $?
0:未找到命令
#找不到“foobar”
grapefruitcat@grapefruitcat:~$ grep foobar test2.sh
grapefruitcat@grapefruitcat:~$ $?
1:未找到命令
true的返回值始终为0,false的返回值始终为1。
&&(与操作符)和 ||(或操作符)属于短路运算符,遵循短路运算法则。返回值和逻辑运算符混合使用可以做条件判断:
false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
false ; echo "This will always run"
# This will always run
在同一行内使用;来连接命令:
grapefruitcat@grapefruitcat:~$ echo "hhh"; echo "bangbang"
hhh
bangbang
命令替换和进程替换
我们要怎样把命令的输出存到变量里面呢?
#把pwd命令的输出存到变量foo里面
grapefruitcat@grapefruitcat:~$ foo=$(pwd)
grapefruitcat@grapefruitcat:~$ echo "$foo"
/home/grapefruitcat
进程替换和命令替换类似,如 <( CMD ) 会执行 CMD 并将结果输出到一个临时文件中,并将 <( CMD ) 替换成临时文件名。即存放在一个匿名文件。
grapefruitcat@grapefruitcat:~$ cat <(ls)
公共的
模板
视频
图片
文档
下载
音乐
桌面
一个大点的例子
#!/bin/bash
echo "Starting program at $(date)" # date会被替换成日期和时间
echo "Running program $0 with $# arguments with pid $$"
# 将所有参数展开,轮流给file变量赋值
for file in "$@"; do
grep foobar "$file" > /dev/null 2> /dev/null
# 如果模式没有找到,则grep退出状态为 1
# 我们将标准输出流和标准错误流重定向到Null,因为我们并不关心这些信息
# 如果没找到foobar,则在此文件后面续上
if [[ $? -ne 0 ]]; then
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file"
fi
done
文件第一行是shebang。说人话就是shebang的内容指定了shell脚本解释器的路径,而且这个指定路径只能放在文件的第一行。第一行写错或者不写时,系统会有一个默认的解释器进行解释。
在计算领域中,Shebang(也称为 Hashbang )是一个由井号和叹号构成的字符序列 #! ,其出现在文本文件的第一行的前两个字符。 在文件中存在 Shebang 的情况下,类 Unix 操作系统的程序加载器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,并将载有 Shebang 的文件路径作为该解释器的参数。
在grep的输出中有几个注意的点:
/dev/null:表示空设备文件0表示stdin标准输入;1>表示stdout标准输出;2>表示stderr标准错误输出;
流可以使用n>运算符重定向,其中n是文件描述符。省略n时,默认为标准输出流1。
通配
- 通配符 - 当你想要利用通配符进行匹配时,你可以分别使用
?和*来匹配一个或任意个字符。例如,对于文件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)
# 输出,8c8表示两个输入在第8行不同,见
# https://www.cnblogs.com/SoaringLee/p/10532503.html
# 8c8
# < x
# ---
# > y
注意,通配符是系统命令使用,一般用来匹配文件名或者什么的用在系统命令中。而正则表达式是操作字符串,以行尾单位来匹配字符串使用的。
其它注意事项:
编写脚本:
shellcheck编写
bash脚本有时候会很别扭和反直觉。例如 shellcheck 这样的工具可以帮助你定位sh/bash脚本中的错误。将 shell 脚本粘贴到 https://www.shellcheck.net 上以获得即时反馈。
脚本首行:
shebang关于
shebang的解释在上文中已有提及。脚本并不一定只有用 bash 写才能在终端里调用。比如说,这是一段 Python 脚本,作用是将输入的参数倒序输出:
#!/usr/local/bin/python
import sys
for arg in reversed(sys.argv[1:]):
print(arg)
内核知道去用 python 解释器而不是 shell 命令来运行这段脚本,是因为脚本的开头第一行的
shebang。在
shebang行中使用env命令是一种好的实践,它会利用环境变量中的程序来解析该脚本,这样就提高来您的脚本的可移植性。env会利用我们第一节讲座中介绍过的PATH环境变量来进行定位。 例如,使用了env的shebang看上去时这样的#!/usr/bin/env python。shell函数和脚本有如下一些不同点:
- 函数只能与shell使用相同的语言,脚本可以使用任意语言。因此在脚本中包含
shebang是很重要的。 - 函数仅在定义时被加载,脚本会在每次被执行时加载。这让函数的加载比脚本略快一些,但每次修改函数定义,都要重新加载一次。
- 函数会在当前的shell环境中执行,脚本会在单独的进程中执行。因此,函数可以对环境变量进行更改,比如改变当前工作目录,脚本则不行。脚本需要使用
export将环境变量导出,并将值传递给环境变量。 - 与其他程序语言一样,函数可以提高代码模块性、代码复用性并创建清晰性的结构。shell脚本中往往也会包含它们自己的函数定义。
- 函数只能与shell使用相同的语言,脚本可以使用任意语言。因此在脚本中包含
主题二:shell工具
查看帮助文档
如何为特定的命令找到合适的参数和使用方法:
最常用的方法为:为对应的命令行添加
-h或--help参数。man工具是常用的文档查阅工具,但有时man调出来的文档会过于详细。tldr是一个不错的替代,它能提供一些使用的样例,简洁明了。(too long dont read)
查找文件
最简单的方法即是一路ls下去找(非常的笨..)
但假设我们要查找一个叫src的文件夹,我们可以使用find命令。find可以递归搜索符合条件的文件,如:
# 查找所有名称为src的文件夹
find . -name src -type d
# 查找所有文件夹路径中包含test的python文件
find . -path '*/test/*.py' -type f
# 查找前一天修改的所有文件
find . -mtime -1
# 查找所有大小在500k至10M的tar.gz文件
find . -size +500k -size -10M -name '*.tar.gz'
除了列出所寻找的文件之外,find 还能对所有查找到的文件进行操作。这能极大地简化一些单调的任务。
# 删除全部扩展名为.tmp 的文件
find . -name '*.tmp' -exec rm {} \;
# 查找全部的 PNG 文件并将其转换为 JPG
find . -name '*.png' -exec convert {} {}.jpg \;
但find工具的语法太过复杂,难以记忆——我们使用fd工具来替代它。
fd工具默认使用正则表达式,默认不分大小写,还可以更改输出颜色,支持unicode。
ubuntu系统下为了避免命名冲突,fd的命令是fdfind,可以自己alias。注意,wsl默认安装的是ubuntu。
从Ubuntu 19.04(Disco Dingo)开始,可以通过使用apt-get调用官方维护的软件包直接安装fd。 如果运行的是旧版Ubuntu,请查看GitHub页面上的安装说明。
获取命令是:sudo apt-get install fd-find。
再有一个是locate工具,find 和类似的工具可以通过别的属性比如文件大小、修改时间或是权限来查找文件,locate则只能通过文件名。

因为是事先搭好了索引,所以搜索非常的快。locate 使用一个由 updatedb负责更新的数据库,在大多数系统中 updatedb 都会通过 cron 每日更新。
查找代码
我们需要查找不仅是文件,还有文件里面的内容。
第一个是grep命令,这是最常用的对输入文本进行匹配的通用工具。grep 有很多选项,这也使它成为一个非常全能的工具。
-C:获取查找结果的上下文;-v:将对结果进行反选,也就是输出不匹配的结果;-R(r):当需要搜索大量文件的时候,使用-R会递归地进入子目录并搜索所有的文本文件。
此外,我们可以使用rg命令对grep -r进行改进:
# 使用ripgrep命令
# 查找所有使用了 requests 库的文件
rg -t py 'import requests'
# 查找所有没有写 shebang 的文件(包含隐藏文件)
rg -u --files-without-match "^#!"
# 查找所有的foo字符串,并打印其之后的5行
rg foo -A 5
# 打印匹配的统计信息(匹配的行和文件的数量)
rg --stats PATTERN
除此还有ack 、ag等工具。
查找shell命令
- 按
↑的方向键会显示你使用过的上一条命令,继续按上键则会遍历整个历史记录; history命令会打印出你使用过的命令,配合管道符还有grep可以查阅你使用过的命令。
语句为:history | grep "** keywords **"
- 对于大多数的shell来说,使用
Ctrl+R对命令历史记录进行回溯搜索。敲Ctrl+R后可以输入子串来进行匹配,查找历史命令行,查找过程也是敲Ctrl+R。按↑退出回溯搜索。
Ctrl+R可以配合 fzf 使用。fzf是一个通用对模糊查找工具,它可以和很多命令一起使用。这里我们可以对历史命令进行模糊查找并将结果以赏心悦目的格式输出。
文件夹导航
使用fasd和 autojump 这两个工具来查找最常用或最近使用的文件和目录。
Fasd 基于 frecency对文件和文件排序,也就是说它会同时针对频率(frequency)和时效(recency)进行排序。
课后练习
阅读
man ls,然后使用ls命令进行如下操作:- 所有文件(包括隐藏文件)
ls -la, Long format list (permissions, ownership, size, and modification date) of all files
- 文件打印以人类可以理解的格式输出 (例如,使用454M 而不是 454279954)
ls -lh, Long format list with size displayed using human-readable units (KiB, MiB, GiB)
- 文件以最近访问顺序排序
ls -u -lt, with-lt: sort by, and show, access time; with-l: show access time and sort by name; otherwise: sort by access time, newest first
- 以彩色文本显示输出结果
ls -l --color=auto
- 所有文件(包括隐藏文件)
编写两个bash函数
marco和polo执行下面的操作。 每当你执行marco时,当前的工作目录应当以某种形式保存,当执行polo时,无论现在处在什么目录下,都应当cd回到当时执行marco的目录。 为了方便debug,你可以把代码写在单独的文件marco.sh中,并通过source marco.sh命令,(重新)加载函数。# 函数内容
grapefruitcat@grapefruitcat:~/bar/a$ cat ~/macro.sh
macro(){
pwd > ~/cur_dir.txt
}
polo(){
# 利用命令替换(管道符不能作为cd输入)
cd $(cat ~/cur_dir.txt)
}
# 执行结果
grapefruitcat@grapefruitcat:~$ cd bar/a
grapefruitcat@grapefruitcat:~/bar/a$ source ~/macro.sh
grapefruitcat@grapefruitcat:~/bar/a$ macro
grapefruitcat@grapefruitcat:~/bar/a$ cd ~
grapefruitcat@grapefruitcat:~$ polo
grapefruitcat@grapefruitcat:~/bar/a$
假设您有一个命令,它很少出错。因此为了在出错时能够对其进行调试,需要花费大量的时间重现错误并捕获输出。 编写一段bash脚本,运行如下的脚本直到它出错,将它的标准输出和标准错误流记录到文件,并在最后输出所有内容。 加分项:报告脚本在失败前共运行了多少次。
#!/usr/bin/env bash n=$(( RANDOM % 100 )) if [[ n -eq 42 ]]; then
echo "Something went wrong"
>&2 echo "The error was using magic numbers"
exit 1
fi echo "Everything went according to plan"
结果展示:
# 首先清空错误流和输出流的两个文件
grapefruitcat@grapefruitcat:~$ >outwrong.txt
grapefruitcat@grapefruitcat:~$ cat outwrong.txt
grapefruitcat@grapefruitcat:~$ >outstream.txt
grapefruitcat@grapefruitcat:~$ cat outstream.txt
# 执行调试脚本,可以见到测试脚本被运行了六次后出错
grapefruitcat@grapefruitcat:~$ ./t3.sh
yeahyeah 1
yeahyeah 2
yeahyeah 3
yeahyeah 4
yeahyeah 5
yeahyeah 6
# 输出流文件展示
grapefruitcat@grapefruitcat:~$ cat outstream.txt
Everything went according to plan
Everything went according to plan
Everything went according to plan
Everything went according to plan
Everything went according to plan
Everything went according to plan
Something went wrong
# 错误流文件展示
grapefruitcat@grapefruitcat:~$ cat outwrong.txt
The error was using magic numbers
代码展示:
#!/usr/bin/env bash
#受测试脚本basesh.sh
n=$(( RANDOM % 100 )) if [[ n -eq 42 ]]; then
echo "Something went wrong"
>&2 echo "The error was using magic numbers"
exit 1
fi echo "Everything went according to plan"
#!/usr/bin/env bash
# 设置两个变量,jud用于循环判断,k用于记录测试次数,注意不能和受测脚本变量名相同,会造成作用域覆盖
jud=0
k=0
while [[ jud -ne 1 ]];
do
# 两个不同的流输入到文件中
source ~/basesh.sh >> outstream.txt 2>> outwrong.txt
# 通过返回值来判断是否有错误流产生
jud=($?)
# 次数自增
let k++
echo "yeahyeah $k"
done
本节课我们讲解的
find命令中的-exec参数非常强大,它可以对我们查找的文件进行操作。但是,如果我们要对所有文件进行操作呢?例如创建一个zip压缩文件?我们已经知道,命令行可以从参数或标准输入接受输入。在用管道连接命令时,我们将标准输出和标准输入连接起来,但是有些命令,例如tar则需要从参数接受输入。这里我们可以使用xargs命令,它可以使用标准输入中的内容作为参数。 例如ls | xargs rm会删除当前目录中的所有文件。利用xargs和cd配合进行目录切换是不可行的,“xargs牵涉写管道,而cd是内部命令。具体的牵涉shell的工作原理。”
您的任务是编写一个命令,它可以递归地查找文件夹中所有的HTML文件,并将它们压缩成zip文件。注意,即使文件名中包含空格,您的命令也应该能够正确执行(提示:查看
xargs的参数-d,译注:MacOS 上的xargs没有-d,查看这个issue)# 我们可以先在文件夹创建一些文件用于操作
grapefruitcat@grapefruitcat:~/missing_sem$ touch file-{a..j}.html image-{1..10}.jpg 'file\ with\ spaces\ {k..z}.html'
grapefruitcat@grapefruitcat:~/missing_sem$ sudo find $(pwd) -name "*.html"
/home/grapefruitcat/missing_sem/file-h.html
/home/grapefruitcat/missing_sem/file-a.html
/home/grapefruitcat/missing_sem/file-f.html
/home/grapefruitcat/missing_sem/file-j.html
/home/grapefruitcat/missing_sem/file-i.html
/home/grapefruitcat/missing_sem/file-e.html
/home/grapefruitcat/missing_sem/file-g.html
/home/grapefruitcat/missing_sem/file-d.html
/home/grapefruitcat/missing_sem/file-c.html
/home/grapefruitcat/missing_sem/file\ with\ spaces\ {k..z}.html
/home/grapefruitcat/missing_sem/file-b.html # 然后就可以用命令完成任务, xargs记得加上参数-d确认分隔符,看输入流,以换行为分隔,
# 使得“即使文件名中包含空格,您的命令也应该能够正确执行”。
grapefruitcat@grapefruitcat:~/missing_sem$ sudo find . -name "*.html" | xargs -d '\n' tar czf t4.tar

如果您使用的是 MacOS,请注意默认的 BSD
find与 GNU coreutils 中的是不一样的。你可以为find添加-print0选项,并为xargs添加-0选项。作为 Mac 用户,您需要注意 mac 系统自带的命令行工具和 GNU 中对应的工具是有区别的;如果你想使用 GNU 版本的工具,也可以使用 brew 来安装。(进阶)编写一个命令或脚本递归的查找文件夹中最近使用的文件。更通用的做法,你可以按照最近的使用时间列出文件吗?
我们在man文档中可以找到一个参数
atime:-atime n
File was last accessed n*24 hours ago. When find figures out how many 24-hour periods ago the file was last accessed, any fractional part is ignored, so to match -atime +1, a file has to have been accessed at least two days ago.但似乎不是很中用啊..
继续向下看,
find有一个格式化输出的参数-printf:我们用
%A@ %p\n就可以实现按访问时间列出文件:(具体字符含义看文档)# 使用sort排序,用tail列出后n行,再用cut剪去前面不必要的字符
grapefruitcat@grapefruitcat:~$ sudo find . -type f -printf '%A@ %p\n' | sort -n | tail -3 | cut -d' ' -f2
./.tldr/tldr/pages/common/cut.md
./.tldr/tldr/pages/common/tail.md
./.config/nautilus/desktop-metadata
大功告成!!
The Missing Semester - 第二讲 学习笔记的更多相关文章
- 深挖计算机基础:MySQL实战45讲学习笔记
参考极客时间专栏<MySQL实战45讲>学习笔记 一.基础篇(8讲) MySQL实战45讲学习笔记:第一讲 MySQL实战45讲学习笔记:第二讲 MySQL实战45讲学习笔记:第三讲 My ...
- MySQL实战45讲学习笔记:第三十九讲
一.本节概况 MySQL实战45讲学习笔记:自增主键为什么不是连续的?(第39讲) 在第 4 篇文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧 ...
- PJ可能会用到的动态规划选讲-学习笔记
PJ可能会用到的动态规划选讲-学习笔记 by Pleiades_Antares 难度和速度全部都是按照普及组来定的咯 数位状压啥就先不讲了 这里主要提到的都是比较简单的DP 一道思维数学巧题(补昨天) ...
- Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver
1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...
- Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥
1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
- 《Linux内核分析》第二周学习笔记
<Linux内核分析>第二周学习笔记 操作系统是如何工作的 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/ ...
- Linux内核分析第二周学习笔记
linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- AS开发实战第二章学习笔记——其他
第二章学习笔记(1.19-1.22)像素Android支持的像素单位主要有px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用 ...
- #Spring实战第二章学习笔记————装配Bean
Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...
- MySQL实战45讲学习笔记:日志系统(第二讲)
一.重要的日志模块:redo log 1.通过酒店掌柜记账思路刨析redo log工作原理 2.InnoDB 的 redo log 是固定大小的 只要赊账记录在了粉板上或写了账本上,之后即使掌柜忘记了 ...
随机推荐
- 你听说过OTA吗?
以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/M660Sc4ey1SxCpRT6vcM9g what? 不知有多少 ...
- Karmada跨集群优雅故障迁移特性解析
摘要:在 Karmada 最新版本 v1.3中,跨集群故障迁移特性支持优雅故障迁移,确保迁移过程足够平滑. 本文分享自华为云社区<Karmada跨集群优雅故障迁移特性解析>,作者:Karm ...
- 【Devexpress】pivotGridControl设置不显示展开折叠按钮
只需要设置.效果看图二
- 【每日一题】【DFS和回溯的区别】【BFS】104. 二叉树的最大深度-211227/220218
给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7], ...
- CyclicBarrier循环屏障源码解析(基于jdk11)
目录 CyclicBarrier循环屏障源码解析(基于jdk11) 1.1 CyclicBarrier概述 1.2 CyclicBarrier原理 1.2.1 基本结构(jdk11) 1.2.2 aw ...
- flask博客项目之tinymce图片上传
查看当前的博客发表情况 截图一张立马粘贴进来 点击发表,显示数据太长 不断撤退回到刚刚页面 删除大图,换成小图,上传方式 点击发表可以成功发表 数据库中查看,是把图片生成这种编码后字符串方式存储的了, ...
- Spring IOC官方文档学习笔记(二)之Bean概述
1.Bean概述 (1) Spring IoC容器管理一个或多个bean,这些bean是根据我们所提供的配置元数据来创建的,在容器内部,BeanDefinition对象就代表了bean的配置元数据,它 ...
- windows通过sshfs挂载linux目录
之前讲过一种方法,PC跟VM在同局域网的情况下,可以用samba的方式挂载linux系统的目录到windows上.但是当PC跟VM不同局域网时这种方式就没办法了. 网络环境 在示意图中,PC只能直连物 ...
- 在IQuery中使用除法提示"Numeric value does not fit in a System.Decimal"
起因 有个需求是需要汇总(单耗=单件用量*1+损耗率)的值,由于现在我们数据库中存的XX率都是放大了一百倍(即10%数据库存的是10),然后就很自然的写了个linq汇总如下 materialOrder ...
- java中String类型的相关知识的简单总结
java中String类型的相关知识总结 一.常用方法: 1.构造方法: byte数组 可指定offset和length 可指定charset char数组 可指定offset和count 字符序列 ...