简单的方法
一些假设:
- 粗体使用
__,斜体使用*(尽管它也可能是**和_)
- 没有“有趣的东西”,比如带有这些字符的(内联)代码,或者转义的
_ 或 *,或者带有前导 * 的列表,这会让我们无法计数
现在,要计算粗体字,我们可以使用
grep -Po '__.*?__' infile.md | grep -o '[^[:space:]]\+' | wc -l
这会查找两对 __ 之间的任何内容。我使用 Perl 正则表达式引擎 (-P) 来启用非贪婪匹配 (.*?);否则,像__bold__ not bold __bold__ 这样的东西只会是一场比赛。 -o 只返回匹配项。
第二个 grep 匹配单词:一个或多个非空格字符的任意序列; wc -l 计算输出的行数。
斜体也一样:
grep -Po '\*.*?\*' infile.md | grep -o '[^[:space:]]\+' | wc -l
要组合这些(粗体和斜体),必须组合命令列表。对于粗体中的斜体:
grep -Po '__.*?__' infile.md | grep -Po '\*.*?\*' | grep -o '[^[:space:]]\+' | wc -l
和粗体斜体:
grep -Po '\*.*?\*' infile.md | grep -Po '__.*?__' | grep -o '[^[:space:]]\+' | wc -l
清理更真实的文件
现在,一个真正的降价文件可能会有一些额外的惊喜(参见“假设”):
* List item with **bold word**
Line with **bold words and \* an escaped asterisk**
Here is an *italicized* word
And *italics with a **bold** word inside*
And **bold words with *italics* inside**
Code can have tons of *, ** and _ and we want to ignore them all
Also `inline code can have * and ** and _ to be ignored`, right?
将呈现为
粗体字和 * 转义星号
这是一个斜体字
并且斜体字里面有一个粗体字
并且内有斜体的粗体字
Code can have tons of *, ** and _ and we want to ignore them all
还有inline code can have * and ** and _ to be ignored,对吧?
清理此类内容的一种方法是使用 sed 脚本:
/^$/d # Delete empty lines
/^ /d # Delete code lines (start with four spaces)
s/`[^`]*`//g # Remove inline code
/^\* /s/^\* (.*)/\1/ # Remove asterisk from list items
s/\\\*//g # Remove escaped asterisks
s/\\_//g # Remove escaped underscores
s/`[^`]*`//g # Remove inline code
s/\*\*/__/g # Make sure bold uses underscores
s/(^|[^_])_([^_]|$)/\1\*\2/g # Make sure italics use asterisks
结果如下:
$ sed -rf md.sed infile.md
List item with __bold word__
Line with __bold words and an escaped asterisk__
Here is an *italicized* word
And *italics with a __bold__ word inside*
And __bold words with *italics* inside__
Also , right?
准备好被第一部分的命令消费了。
把它们放在一起
将markdown文件名作为参数的脚本中的所有内容:
#!/bin/bash
fname="$1"
tempfile="$(mktemp)"
sed -r '
/^$/d
/^ /d
s/`[^`]*`//g
/^\* /s/^\* (.*)/\1/
s/\\\*//g
s/\\_//g
s/`[^`]*`//g
s/\*\*/__/g
s/(^|[^_])_([^_]|$)/\1\*\2/g
' "$fname" > "$tempfile"
bold=$(grep -Po '__.*?__' "$tempfile" | grep -o '[^[:space:]]\+' | wc -l)
italic=$(grep -Po '\*.*?\*' "$tempfile" | grep -o '[^[:space:]]\+' | wc -l)
both=$((
$(grep -Po '__.*?__' "$tempfile" |
grep -Po '\*.*?\*' | grep -o '[^[:space:]]\+' | wc -l)
+
$(grep -Po '\*.*?\*' "$tempfile" |
grep -Po '__.*?__' | grep -o '[^[:space:]]\+' | wc -l)
))
rm -f "$tempfile"
echo "Bold words: $bold"
echo "Italic words: $italic"
echo "Bold and italic words: $both"
可以这样使用:
$ ./wordcount infile.md
Bold words: 14
Italic words: 8
Bold and italic words: 2
不足之处
- 这可能会被包含下划线的单词所干扰。一些降价风格会忽略这些,并认为它们是单词的一部分。
- 我确定我在清理过程中遗漏了一些边缘情况