假设我有一个名为tables.tex的文件(许多为tex格式化的表,包括序言),其中包含如下行:
some words (xyz, abc) & 0.00071 (0.07846) & 0.00411 (-0.13542) \\
some more words (1) & 0.00341 (-0.59991) & 0.00001 (0.99453) \\
我需要找到以双反斜杠结尾的行中第一个“&”之外的括号中的所有数字,并将它们替换为四舍五入到 3 位数字的四舍五入版本。所以我上面两行的输出如下所示:
some words (xyz, abc) & 0.00071 (0.078) & 0.00411 (-0.135) \\
some more words (1) & 0.00341 (-0.600) & 0.00001 (0.995) \\
做到这一点最有效的方法是什么?我在这个网站上找到了答案,描述了如何以各种方式执行此操作的某些部分(舍入数字、括号中的打印数字、awk、perl 等),但我很难将它们全部放在一起(实际上工作)风格。
答案1
Awk 或 Perl 是完成这项工作的好工具。Perl 更容易实现,因为它可以将任意代码应用于正则表达式匹配。
perl -pe '
if (s/^([^&]*&)//) { # if there's a &, then strip the prefix…
print $1; # and print it
s[\((-?[0-9]*\.[0-9]+)\)] # replace decimal numbers in parentheses…
[sprintf("(%.3f)",$&)]eg # …by their rounding
}
'
答案2
. 4<<HERE /dev/fd/4
echo "$(sed -rn '/\\\\/{:l;s/([^&]*&.*\()([-0-9.]*)(\).*)/\
"\1$(printf "%.3f" "\2" )\3"/;tl;p;}'<<\SED
some words (xyz, abc) & 0.00071 (0.07846) & 0.00411 (-0.13542) \\
some more words (1) & 0.00341 (-0.59991) & 0.00001 (0.99453) \\
SED
)"
HERE
输出:
some words (xyz, abc) & 0.00071 (0.078) & 0.00411 (-0.135) \\
some more words (1) & 0.00341 (-0.600) & 0.00001 (0.995) \\
显然这与 @Gilles 的答案非常相似 - 我刚刚意识到 - 我们都使用printf
完成四舍五入。我想在这种情况下这可能是给定的,因为这就是它的作用。当然,这仅使用 shell 结构,sed
实现相同的目标,但如果您可以使用他推荐的工具,它们可能会更快。
不过,我们的逻辑有一个明显的例外。这使用分支测试 - 因此需要 GNUsed
- 递归字符串以查找可能的遗漏。 Gilles 在搜索之前打印并删除字符串中未使用的部分,这可能会更快。如果我必须在两者之间做出选择,我会选择他的。尽管如此,我相信这个答案本身就足以保留。