第 10 期:你为什么不更新你的个人网站?

@Author : Lewis Tian (taseikyo@gmail.com)

@Link : github.com/taseikyo

@Range : 2021-01-03 - 2021-01-09

Weekly #10

readme | previous | next

总字数:7099 个(汉字:3357,英文单词:1102,数字:614,中文标点:368,英文标点:1658),阅读时长约:13 分 43 秒。

*Photo by 百万剪辑狮 on Bilibili

灵明无着,物来顺应,未来不迎,当时不杂,既过不恋。

Table of Contents

  • algorithm

    • Q53 同数包夹

  • review

    • Bash 测试和比较函数(英文)

  • tip

    • Bash 脚本中 ((([[[ 的区别(知乎)

    • PDF 转 EPS(StackOverflow)

    • 提高 GitHub 浏览体验的插件、脚本

  • share

    • 你为什么不更新你的个人网站?(英文)

algorithm

这里有分别标了数字 1 ~ n 的两副牌,共 2n 张。把这些牌排成一排,然后两张 1 的中间放一张牌,两张 2 的中间放两张牌……两张 n 的中间放 n 张牌。举个例子,当 n = 3 的时候,有如 图 1 所示的两种排列方法。求当 n = 11 时共有多少种排列方法?

好难啊,完全没思路,果然没有高强度刷题之后脑子生锈了。

题解:回溯

  • 我们使用一个长度为 2n 的数组 cards 表示每一个位置的牌,如果当前位置还没有放牌,那么对应的数字为 0;

  • 我们用递归 + 回溯的方法枚举所有可能的情况。具体地,我们用 dfs(num) 表示当前正在尝试放入两张数字为 num 的牌,即在 cards 中找出所有间隔为 num 的两个位置,放入数字为 num 的牌。随后我们调用 dfs(num+1) 递归地进行搜索,当搜索到 dfs(n+1) 时,表示搜索完成,找到了一种满足要求的排列方法,并将答案增加 11。

这个定义函数的方式有点意思,有点像 js 里面的写法。

回溯跟动态规划两种 bug 题都算是有套路的,可能难在思路,要是有想法直接套模板就可以了。

review

一直觉得 https://developer.ibm.com 这个网站的博客质量很高,不过我看过的基本都是 200x 的博客了,一直想将那些网页保存为 Markdown,一直拖到现在也没做,该死的拖延症。

这篇文章是承接 Tip#1 中讲 Bash 的各种括号的,Tip#1 不是给了个 全网最全的 bash 速查表 吗,在该表中说 "# 如果不考虑兼容 posix sh 和 dash 这些的话,可用 bash 独有的 ((..)) 和 [[..]]: https://www.ibm.com/developerworks/library/l-bash-test/index.html" ,给出的链接就是此博客,于是顺便康康。

Understanding the various tests and knowing that the shell can also interpret some operators as shell metacharacters is an important step to becoming a power shell user.

确实,现在大多 Linux 发行版的默认 Shell 基本都是 Bash,虽然我会将默认 Shell 改成 Zsh,但是有时候命令不支持我还是得切回 Bash,不得不说 Bash 还是最强大(在我用过的几个 Shell 中)。

在 Bash 中 test expr[ expr ] 是等价的,可以使用 $? 获取返回值(0 (True)、1 (False)),也可以在 && || 中使用返回值:

可以使用 -eq -ne -lt -le -gt -ge 来进行算数比较,= != < > 来比较字符串(注意等于是 =),-z 测试空字符串,-n 或者不适用运算符测试非空字符串([ "a" ] && echo True [ -n "a" ] && echo True

文件测试

Operator
Characteristic

-d

Directory

-e

Exists (also -a)

-f

Regular file

-h

Symbolic link (also -L)

-p

Named pipe

-r

Readable by you

-s

Not empty

-S

Socket

-w

Writable by you

-N

Has been modified since last being read

-nt

Test if file1 is newer than file 2. The modification date is used for this and the next comparison.

-ot

Test if file1 is older than file 2.

-ef

Test if file1 is a hard link to file2.

文件权限也可以检查,这里没列出来,毕竟能测读写,其他应该都能测。

-o 操作符允许您测试可以使用 set -o 选项设置的各种 shell 选项:

-a 和 -o 选项分别表示逻辑 "与" 和 "或","非" 则是 !,可以使用括号对表达式进行分组并覆盖默认优先级。

shell 通常会在子 shell 中的括号之间运行一个表达式,因此需要转义括号,或者使用单引号或双引号将括号包起来:

Test 命令非常强大,但是考虑到它对转义的要求以及字符串和算术比较之间的差异,这个命令有些笨拙。

(( )) 复合命令计算算术表达式的值,如果表达式的值为 0,则将退出状态设置为 1,如果表达式的值为非零,则将退出状态设置为 0,不需要在 (( )) 之间转义操作符,可以执行通常的 c 语言算术、逻辑和位操作。

Let 命令还可以执行一个或多个算术表达式,它通常用于给算术变量赋值。

(()) 一样,[[ ]] 复合命令允许你对文件名和字符串测试使用更自然的语法,可以使用括号和逻辑运算符组合 test 命令所允许的测试。

当使用 = 或 != 的时候,[[ 命令也可以在字符串上做模式匹配,匹配的行为与通配符全局化相似:

你甚至可以在 [[ ]] 中做算术测试,但要小心。除非在 (()) 中,否则 < 和 > 操作符将比较操作数作为字符串,并测试它们在当前排序序列中的顺序。

虽然可以使用上面的测试以及 &&|| 控制操作符完成大量编程,但是 bash 包含了更为熟悉的 if,then,else 和 case 结构。

虽然上面的测试只返回 0 或 1 个值,但命令可能返回其他值。

Bash 中的 if 命令有一个 then 子句,其中包含当 test 或 command 返回 0 时将执行的命令列表,一个或多个可选的 elif 子句,每个子句都带有一个额外的测试和 then 子句和一个相关的命令列表,一个可选的最终 else 子句和一个如果 if 或 elif 测试都不为真将执行的命令列表,以及一个标记结构结束的终端 fi。

看了上面的函数,深感 Bash 牛逼,为什么是这样的结果,因为 (( )) 命令会执行算数操作,而 "$* 注 1会将参数展开为 "$1 $2 $3 ..." 这样,所以第一条命令为 (( 3 + 4 )) 所以为 7。

local 声明 x 为局部变量,let/declare 有若干选项。

可以看到最后两个例子,将 xyz 传递给 mycalc 并不是一个错误,而是计算为 0,这个函数不够聪明,无法识别最终使用示例中的字符值,因此无法向用户发出警告,你可以使用一个字符串/模式匹配测试:

shell 允许基数最多为 64(bash#value),因此您可以在输入中合法地使用任何字母字符,以及 _ 和 @

可以使用 $((expression)) 和 echo 命令执行 shell 算法。这样你不会学到任何关于函数或者测试的东西,但是请注意,shell 在内部 ((expression)) 或者 [[ expression ]] 时不会解释元字符,比如 *。

更多可以阅读:https://developer.ibm.com/tutorials/l-lpic1-map/

tip

这是个老问题了,老是查了忘,忘了查。。。

@韦易笑:一句话说清楚:只有单中括号 [ ] 是兼容 posix shell 标准的,比如 Bourne shell(/bin/sh),ash,dash 这些,而其他一切双方括号,双圆括号都不兼容 posix shell 标准,而是 bash 特有的语法扩展。

所以如果你不当要使用 bash,有时候还需要看懂或者修改各种系统管理脚本的话,你需要先把 [ ] 了解清楚。标准的 if 语句格式为:

条件为真,结果输出 0,否则输出 1,更多用法用 man test 查看:

有了 test 这个程序,结合我们的 if 命令就可以在各种 posix shell 中进行条件判断了,test 这个程序还有一个孪生兄弟,单左括号 [ 命令,这是一个可执行程序,位于 /bin 或者 /usr/bin 下面,它的使用方法和 test 完全一样,只是要求最后一个参数后要多加一个右括号,比如:

所以单中括号写起来更优雅一些而已

到此为止,单中括号已经完全说清楚了,如果不兼容 posix shell的话,可以用 bash独有的 [[ expression ]] 进行字符串判断,(( express )) 进行整数判断。更多 bash 技巧见:全网最全的 bash 速查表

使用 draw.io 作图可以导出 svg 和 pdf,然而 LaTex 插入 svg 挺麻烦的,懒得查了;而导出的 pdf 是 A4 格式的,有大片空白,于是搜到这个答案。

安装完 texlive(直接用 Scoop 安装 latex 也有)就会有这个答案所需的几个工具,下面代码是原答案,我稍作了修改,可以自定义生成的 eps 名称:005_convert_pdf_to_eps.sh,直接在 wsl 中运行(wsl 真方便)。

3. 提高 GitHub 浏览体验的插件、脚本

这算是我的一个简单使用体验总结,下面是我感觉能提高不少浏览体验的插件和脚本。

在浏览器左侧显示整个 repo 的目录、文件结构,对于嵌套了几层的文件来说可以展开文件夹点击跳转,很方便的一个插件。

是一个所谓的悬浮卡,就是将鼠标放在 GitHub 链接上面就会显示其内容,比如鼠标停在某个 issue 链接上,就会有个 "悬浮卡片" 显示 issue 的标题和内容,很好用的一个插件。

扩展 GitHub 源码查看、跳转功能的插件。

在 GitHub 的 issues 页面显示曾经评论过的 issue,可以方便找到自己之前留言过的 repo。

浮动显示 README 的目录,其实这是作者的一系列脚本中的一个,还有很多可以去他的 GitHub 或者直接在 GF 发掘。

share

我跟作者有类似的体验,在刚建站的时候活力满满,激情四射会经常更新内容,但后来就慢慢鸽了,为什么不更新你的个人网站了?

作者列出来几个原因:

  1. Nothing to say,确实,有时候思想枯竭没啥好说的也就不更新了。

  2. Not everything is evergreen,技术总是在更新,你无法保证你前面发布的东西就总是对的,可能后面就发现有问题。

  3. Too hard to add and edit content & A rigid app structure disincentivizes new ideas & Updating and deploying takes too long,后面这三个说的是工具的原因,我觉得跟这个没关系,如果遇到这些原因,那说明自己没调研好,没找对开发和部署工具。

至于我为什么不更新个人网站了,主要原因是没啥说的,然后可能就是作者说的第二点,Not everything is evergreen,我现在个人网站(GitHub Page)主要是记录遇到的问题,以及学到的一些技巧,或者一些感悟和吐槽。其实很多跟另一个 repo 重合了,导致有些东西没写,下面是今年写的一些东西:

date
title

2020-01-06

Xshell 无法连接服务器

2020-01-08

vscode 通过跳板机连接服务器

2020-03-09

VMware 安装 Ubuntu1910 虚拟机无法上网

2020-03-16

Ubuntu 安装 oh-my-zsh、autojump 和 autosuggestions

2020-04-02

【Windows/Scoop】Scoop 的安装使用

2020-05-28

git push 每次都要输入用户名密码的问题

2020-06-09

新科娘《梦回还》之清风最梦事件

2020-08-13

【C++】每日 Bug - int 转 string

2020-08-25

【C++】每日 Bug - int 转 double

2020-09-30

向 TheAlgorithms/Python 贡献代码须知

2020-10-07

解决 Ubuntu18.04 的 dpkg warning files list file for package 'XXXXXXX' missing, assuming package has no files currently installed bug

2020-10-07

有用的 bash alias

2020-10-09

CentOS 和 Ubuntu 命令区别列表总结

2020-10-13

Linux 个人使用配置

2020-10-15

忘记 root 密码如何找回或者重置?

2020-10-16

赋予普通用户 sudo 的权限方法

2020-10-22

Windows 应用商店错误代码 0x80131500

2020-11-02

如何在公共使用的服务器保证隐私?

2020-11-07

inside 游戏完结体会

2020-11-11

如何在另一个服务器节点运行 OSv 镜像

2020-11-24

Windows TIM 登录超时解决办法

2020-12-04

入坑 VTuber 的我

2020-12-11

是时候从 os.path 转向 pathlib 了

2020-12-16

zsh 历史文件编码问题

2020-12-21

vscode LaTex 表格编译错(长时间 build 卡住)

2020-12-24

WSL 转化为 WSL2 的错误解决方案

没想到也摸了 26 篇,不得不说一个所谓 "局部性" 的问题,一个犯过的错,将来很有可能会再犯,当你记录下来将来就不需要再去搜各种没用的办法,直接用以前的方法搞定。就比如 TIM 登录超时的问题,现在基本每个星期都会遇到一次,真是有毒。

所以说好记性不如烂笔头,记笔记还是很有用的,毕竟只要出现了错误,那么你肯定不孤独,必然有其他人也犯过或者将来会犯。

话说回来,你有多久没更新朋友圈了?


注 1:"$*" 和 "$@" 都表示传递给函数或脚本的所有参数,不被双引号 ("") 包含时,都以 "$1" "$2" ... "$n" 的形式输出所有参数。 但是当它们被双引号 ("") 包含时,"$*" 会将所有的参数作为一个整体,以 "$1 $2 ... $n" 的形式输出所有参数;"$@" 会将各个参数分开,以 "$1" "$2" ... "$n" 的形式输出所有参数。

readme | previous | next

最后更新于

这有帮助吗?