用GNU-sed给Markdown文本打补丁

方法说明 & 各种坑的提示

Posted by koyo on February 16, 2016

昨天拜读了某位大牛的文章,发现有拼写错误;看样式估计是用Markdown写的,就试图用sed给打补丁。 在此,总结一下所用到的方法和技术上的几个小坑。

Mac上的sed

Mac上的sed跟常用的Linux发行版(如Ubuntu)上的sed不同;前者属于标准的POSIX sed,后者属于增强型的GNU sed增强 体现在哪里呢?支持的参数/选项不同,功能更强大……

重点在于 —— GNU sed用的是我们所习惯的标准正则语法,而Mac自带的POSIX sed不是!!!
e.g.
空白字符(空格/制表符)在GNU sed中表示为\s
而在POSIX sed中却表示为坑爹的[[:space:]]

果断换GNU-sed;参考这里

brew install -y gnu-sed
echo "alias sed=gsed" >> ~/.zshrc

sed多行匹配

sed本质上是个“流编辑器”,换句话说:是一行一行地处理文本的。 因此,并没有特别优雅的方法来解决这个问题。 stackexchange上的这篇文章提供了一种基于标签的解决办法:

sed -i ':a;N;$!ba;s/\n/,/g' test.txt

解释一下:

  1. :a create a label via :a
  2. ;N append the current and next line to the pattern space via N
  3. $!ba if we are before the last line, branch to the created label $!ba ($! means not to do it on the last line (as there should be one final newline)).
  4. s/\n/,/g finally the substitution replaces every newline with a comma on the pattern space (which is the whole file).

colordiff -u

Mac上自带的diff样式比较丑,可以换成colordiff;另外,开-u选项可以渲染成类似git diff的样式。ref http://qiita.com/catatsuy/items/8bafef2a60762a1c9f0f

brew install colordiff
echo "alias diff=colordiff -u" >> ~/.zshrc

脚本

OK,有了上述基础;可以写脚本了。

#!/bin/bash

gsed -i.backup \
	-e "s/电活/电话/g" \
	-Ee ":a;N;$bash;s/使\s{2,}\n\s*用/使用/g" \
	-e "s/使<br ?\/?>用/使用/g" \
	$1

echo "========== diff START =========="
colordiff -u $1.backup $1
echo "========== diff END =========="

echo "========== you can run 'rm -rf $1.backup' after confirm it =========="
  1. 看起来比较奇怪的那一行是在处理“两个空格加一个回车”的模式,在markdown中这个会被转成<br />
  2. gsed中的-i选项是直接跟后缀名的,中间不用加空格
  3. 选项-E是打开高级扩展;有时候要加上(在zsh中直接用好像又不支持,很奇怪)
  4. $!ba不知为何自动变成了$bash;但是不影响结果(而且,直接写$!ba反而会出错)

基于wget做自动运行

把补丁脚本push到网上,然后把下列命令发给作者即可。
这里我用的是/dev/stdin,应该也可以用xargs之类的方法吧。初步试了试,好像比较麻烦,就算了。

wget http://koyo922.github.io/share/patch_time_friend.sh -O- | bash /dev/stdin <your_source_file.md>