我有数百个文本文件,其中包括化学式以及包括数值的叙述。公式前面始终有空格,但后面可以有空格、逗号、句点等。
问题是:公式未格式化为将数字显示为下标,例如:
H2SO4、C5H11OH。
我想将下标格式化为 HTML 标签,例如:
H<sub>2</sub>SO<sub>4</sub>, C<sub>5</sub>H<sub>11</sub>OH
这样下标就会以 HTML 形式呈现,例如:
H 2 SO 4 , C 5 H 11 OH
我曾经尝试过用 Java、php 等来实现这一点,但实现必然是混乱和尴尬的。我怀疑有一种优雅的 sed/awk 方法。
显然,解决方案的一部分是制作一个正则表达式,匹配一个字母后跟一个或多个数字,作为公式检测机制(可能会出现误报,我稍后会手动纠正)。然后,给定如此确定的公式,sed 替换需要在每个数字或数字序列之前添加标签sub
,并在其后添加子标签闭合。
肯定有一句台词可以做到这一点,但我无法理解。
有任何想法吗?
答案1
例如:
sed -r 's:([A-Za-z])([0-9]+):\1<sub>\2</sub>:g'
应该做这项工作。
(匹配一个字母后跟一组数字,并将其记住为 \1 和 \2。将所有这些替换为相同的字母 (\1) 加上标记中包含的数字组 (\2) sub
。)
答案2
由于您提到可能存在误报,需要稍后手动更正,因此您可能需要考虑一种稍微更稳健的形式,其中包含以下限制:
- 所有化学符号开始带有一个大写字母。
- 所有化学符号要么是一个大写字母,要么是一个大写字母后跟一个小写字母,除了临时指示符我会忽略这一点。
鉴于这些你可以尝试,例如:
sed 's|\([[:upper:]][[:lower:]]\{0,1\}\)\([0-9]\{1,\}\)|\1<sub>\2</sub>|g'
使用非 POSIX-r
选项,可读性会稍好一些,但可移植性较差:
sed -r 's|([[:upper:]][[:lower:]]?)([0-9]+)|\1<sub>\2</sub>|g'
通过确保全部的正在处理的“单词”不包含连续的小写字母,当然可以通过专门检查每个可能的化学符号来进一步改进,但这会变得越来越花哨,但回报却越来越少。上述内容应该已经大大减少了误报。
答案3
分组和反向引用就是诀窍。感谢您朝着正确的方向推动。最后,我使用了以下内容:
sed 's/\([A-Z][a-z]*\)\([0-9][0-9]*\)/\1<sub>\2<\/sub>/g' file
这可以容忍文档中出现标题(例如 h2)的情况。