logo学习随笔

bash 脚本入门

July 31, 2020

前言

最近深感能力不足,于是开始了每日的 leetcode 刷题。为了以后复习方便,单独开了一个仓库进行存档。每道题目为单个 md 文件,commit 记录为题目的名称 :white_check_mark: 347. Top K Frequent Elements.md

建档步骤枯燥且重复

起初决定以每道题目的名称作为文件名,内容的标题也是题目名,即 # 347. Top K Frequent Elements

由于是新增文件,所以 git status 输出的内容为:

On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        347. Top K Frequent Elements.md

nothing added to commit but untracked files present (use "git add" to track)

这种格式的文本显然很难去提取当前需要提交的文件名,所以需要去了解 git status 有没有一个标准化的输出格式。

探索解决方案

在考虑通过脚本解决上述问题时,考虑到新增和提交是两个步骤,所以分为两个独立的脚本。

新增脚本

首先新增文件的脚本比较简单,就是通过输入文件名,以此来生成文件和标题:

#!/bin/bash

set -e

problem=$@

if [[ $@ == "" ]]; then
    echo "Please enter the problem name."
else
    echo "# $problem" >> "$problem.md"
fi

由于对 bash 还是比较陌生,所以可能水平有些次。不过虽然看起来很简单,但是这里有一个技巧:就是 $@ 会拿到执行该脚本时传入的所有 arguments。为什么不能拿 $1 来获取题目呢?这就是遇到的一个坑点:在执行脚本时跑的命令是:./bin/add_problem.sh 347. Top K Frequent Elements.md,结果 $1 的值为 347. 而不是预期的整个标题内容。

提交脚本

通过获取当前待提交的文件名,并提交推送至远程仓库:

#!/bin/bash

set -e
# https://stackoverflow.com/a/5238537/6796500
file=$(git status --porcelain | sed s/^...//)

if [[ $file == "" ]]; then
    echo "No files changed."
else
    git add .
    git commit -m ":white_check_mark: $file"
    git push
fi

这里最重要的一点就是拿到所有变更的文件名,经过搜索发现果然有人提过这个需求:https://stackoverflow.com/a/5238537/6796500

那么就好办了,直接把拿到的文件名加入到 commit message 中,然后执行 git 操作。

总结

虽然目前基本满足了个人需求,但是这里还有一点遗憾,就是 git status 可以拿到多个变更文件。本来可以通过 for loop 来提交多个 commit,但是还是遇到了先前的问题:

347. Top K Frequent Elements.md
78. Subsets.md

这里变更了两个文件:$files,但是 for $file in $files 得到的 $file 却是:347.TopK 等。这是目前待解决的问题。如有解决方案,还请帮忙提供解决方式:https://github.com/keisei77/algorithm-practice/issues/1,不胜感激。

通过写简单的脚本,确实提高了部分效率,也对 bash 的使用有了新的认知。