sc:古老的电子表格计算器

作者:Serge Hallyn

哇,Linux 的软件真是太多了——太多软件了! 瞧,如果你想要一个浏览器,你可以在 Firefox、Opera、Chrome、Galeon、Surf 和许多其他浏览器之间进行选择。 而且,在命令行中,wget、curl、Lynx、ELinks 等也可用。 对于电子邮件,选项包括 Evolution、KMail、Balsa 和 xmh;或者在命令行中,你可以使用 mutt(我的最爱)、sup、pine、mh 和无数其他工具。 日历选择包括 GNOME 日历、KDE 日历、xcal 和 Evolution;或者,在终端中,你可以使用功能非常强大的 Remind 或 ccal,更不用说 Google 日历的命令行界面了。 对于电子表格,你有 OpenOffice.org 的 OOCalc、Gnumeric、KSpread 和 Xspread;或者,在终端中,你可能拥有所有电子表格中最好的一个,sc,特别是如果你是 vi 的粉丝。

我使用 sc 多年了,主要用于预算和项目规划。 我发现的最早版本是 Robert Bond 于 1987 年 8 月 18 日发布到 comp.sources.unix 上的版本(见“资源”),但那已经是 4.1 版本了。 该帖子说它以前被称为 vc,并且最初版本是由 James Gosling(Java 语言的创始人)于 1982 年 9 月编写的。 虽然 sc 的文档很难找到,但它确实带有一个不错的 man 页面和一个简洁的教程,你可以直接加载到 sc 中。 它还使用与 Xspread 相同的文件格式,因此现有的关于 Xspread 中公式的文档(比 sc 的文档更丰富)也可能有所帮助。

基本用法

如果你使用 Debian 或 Ubuntu,只需输入sudo apt-get install sc。 如果你的发行版没有 sc 包,请参阅“资源”以获取源代码的链接。 通过在终端中输入以下内容启动程序:sc,你将看到一个类似于列表 1 的屏幕。因为它基于 curses,所以你可以在慢速链接上运行它,以及在 screen 内部运行它,这样你就可以从另一个终端分离和重新连接。 有一个非常详细的 man 页面,它(在 Ubuntu 包中)指出你可以通过执行以下操作来启动带有教程的 sc:

sc /usr/share/doc/sc/tutorial.sc

实际上,这不太正确。 在 Ubuntu 中,首先你需要解压缩教程

sudo gunzip /usr/share/doc/sc/tutorial.sc.gz

然后启动它。

列表 1. 启动 sc

sc 7.16:  Type '?' for help.

        A         B         C         D         E
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20

如果你更喜欢立即开始使用一些真实数据,这里有一些有用的命令。 像 vi 一样,sc 在命令模式下启动。 vi 移动键 hjkl,在单元格之间左右上下移动,正如你所期望的那样。 要直接跳转到单元格 D3,请按 gD3。 你可以使用 = 开始输入数值或公式。 要优雅地中断命令,请按 Ctrl-G。 有关更简单的命令,请参阅“命令模式下的基本 sc 用法”侧边栏。

命令模式下的基本 sc 用法

  • hjkl — vi 键移动(或光标键)。

  • gB13 — 转到单元格 B13。

  • ir, ic — 插入行,插入列。

  • ma (mb, mc 等) — 将单元格“标记”为 a(或 b,或 c 等)。

  • ca (cb, cc 等) — 复制先前用 ma 标记的内容。

  • Ctrl-f, Ctrl-b — 向上或向下翻页(也可用 pgup, pgdown)。

  • dr, yr, pr — 删除行,复制行,粘贴行。

  • dc, yc, pc — 删除列,复制列,粘贴列。

  • dd, yd, pd — 删除单元格,复制单元格,粘贴单元格。

  • = — 输入数值(25 或 F13-D14)或公式 (@sum(A2:A145))。

  • < — 插入左对齐文本。

  • \ — 插入居中对齐文本。

  • > — 插入右对齐文本。

  • x — 移除单元格。

  • W<filename.asc> — 写入纯文本文件。

  • P<filename.sc> — 写入 .sc 文件。

  • G<filename.sc> — 读取(“get”) .sc 文件。

  • Zr, Zc — zap(隐藏)行或列。

  • sr, sc — 显示行或列。

  • @ — 强制重新计算。

  • e — 编辑数值。

  • E — 编辑字符串值。

对我来说,使用电子表格最重要的三件事是:轻松添加新数据、移动数据和定义自动重新计算的简单公式。 sc 在前两个要求方面表现出色,这得益于其类似 vi 的命令模式。 它在公式方面也做得很好。 查看在线帮助以获取大量公式列表,但根据我的经验,最常用的函数是简单加法。 这在 sc 中与任何其他电子表格没有什么不同。

要将 A3 到 A10 中的值之和放入 A12,请转到单元格 A12,然后输入=@sum(A2:A10)。 要编辑公式,请按 e 进行编辑,你将在顶行处于命令模式,编辑公式。 像在 vi 中一样编辑,然后按 Return 键保存编辑后的公式。

如果要在第 5 行之前插入五个更多行,请转到单元格 A5,然后输入5ir,这意味着“执行 5 次:插入一行”。 公式(现在在 A17 中)将自动更新为@sum(A2:A15)。 现在你可以通过转到 A17,输入ma,然后转到 B17 并输入ca,将该公式复制到单元格 B17。 公式将自动更新为@sum(B2:B15).

如果你想在电子表格中突出显示一些特定数据,而无需实际删除行,则可以隐藏不感兴趣的行。 这在 sc 中称为 zap,你可以通过按 Z,然后按 r 表示行或 c 表示列来执行此操作。 (如果你在它之后再按 Z,sc 会认为你的意思是保存并退出,就像 vi 中的 ZZ 一样。) 你可以使用 S 表示显示来取消隐藏,然后再次按 r 或 c。 同样,你可以输入30Zr来 zap 30 行。

我已经提到了教程和详细的 man 页面,但 sc 也有在线帮助,你可以通过按 ? 来查看。 在那里,你将找到可以切换的设置、移动光标的方法、财务函数列表等等。

文件保存和更多

要保存文件,请按 P,后跟文件名,例如 budget.sc。 要保存纯文本表示形式,请按 W,后跟文件名,例如 budget.asc。 我发现这些特别有用,不仅可以快速粘贴到电子邮件中,还可以轻松浏览一组电子表格。

你还可以输出其他格式。 例如,要输出 LaTeX 表格以粘贴到论文中,请输入S(表示设置)tblstyle=latex,然后输入T(表示表格输出)output.tex。 当然,生成的 LaTeX 表格也适用于通过添加图像、字体、颜色等进行无休止的美化选项。 对我而言,纯文本几乎总是最有用的。

为了与其他电子表格程序交换数据,sc 以冒号分隔的格式导出。 不幸的是,这会导出公式的结果,而不是公式本身,但这仍然可能有用。

你可以通过输入以下内容在 sc 中输出冒号分隔的文件S(表示设置)tblstyle=0,然后输入T(表示表格输出)output.cln。 实际上,0 是默认的 tblstyle,因此如果你之前选择了另一种格式(例如 LaTeX),则只需要执行第一步 (S)。

要在 OpenOffice.org 的 OOCalc 中导入此文件,请打开 OOCalc,转到“插入”菜单,然后选择“从文件选择”。 浏览到你的 output.cln 文件并选择它。 你将获得一个带有“分隔符选项”部分的导入屏幕。 对于“分隔符”,选择“其他”,然后输入冒号。 确保取消选择所有其他“分隔符”选项,否则它将无法正常工作。

不幸的是,尽管 sc 可以导出其他格式,但它不导入它们。 但是,你可以解决这个问题。 一种方法是从获取 CSV 输出开始。 例如,这应该是你的在线银行对账单的一个选项。 从 OOCalc 中,选择“另存为”→“文本 CSV 格式”,然后单击“编辑过滤器设置”。 如果下一个弹出窗口警告你有关在此格式中丢失信息的信息,请单击“保留当前格式”。 在“字段选项”弹出窗口中,取消选择“按显示方式保存单元格内容”;否则,数值将被放在引号中。 对于字段分隔符,让我们使用 :,因为这是 sc 输出的格式。 假设 import.csv 是结果文件的名称。

可能有很多种方法可以将此数据导入 sc。 例如,sc 提供了你可能能够使用的高级宏。 但是,我认为最简单的方法是将 CSV 文件转换为有效的 sc 格式文件。 这很容易,因为 sc 格式本身是简单的纯文本——这是我喜欢 sc 的另一个原因。

列表 2. 用于将 CSV 文件转换为 sc 格式的 Python 脚本

#!/usr/bin/python

import sys
import string

if len(sys.argv) < 2:
    print "Usage: %s infile [outfile] [delimiter_char]" % sys.argv[0]
    sys.exit(1)

filename_in = sys.argv[1]

if len(sys.argv) > 2:
    filename_out = sys.argv[2]
    outfile = open(filename_out, 'w')
else:
    outfile = sys.stdout

delimiter = ':'
if len(sys.argv) == 4:
    delimiter = sys.argv[3][0]
    print 'using delimiter %c' % delimiter

infile = open(filename_in, 'r')

letters = string.ascii_uppercase
text = ["# Produced by convert_csv_to_sc.py" ]
row=0
for line in infile.readlines():
    allp = line.rstrip().split(delimiter)
    if len(allp) > 25:
        print "i'm too simple to handle more than 26 many columns"
        sys.exit(2)
    column = 0
    for p in allp:
        col = letters[column]
        if len(p) == 0:
                continue
        try:
            n = string.atol(p)
            text.append('let %c%d = %d' % (col, row, n))
        except:
            if p[0] == '"':
                text.append('label %c%d = %s' % (col, row, p))
            else:
                text.append('label %c%d = "%s"' % (col, row, p))
        column += 1
    row += 1

infile.close()
outfile.write("\n".join(text))
outfile.write("\n")
if outfile != sys.stdout:
    outfile.close()

列表 2 中的 Python 脚本只是逐个遍历 CSV 值,写出 sc 命令以插入文本和数值。 请注意,如果 CSV 支持公式,那么插入公式也很容易。 通过输入以下内容运行此脚本

python c.py import.csv import.sc

如果你的 CSV 文件由冒号以外的字符分隔,例如逗号,请添加分隔符作为最后一个选项

python c.py import.csv import.sc ','

现在,打开电子表格,使用

sc import.sc

,你的在线银行对账单或简单的 OpenOffice.org 电子表格现在在 sc 中打开了。

你可以更进一步,将 c.py 变成一个自动插件。 但是,请注意,此支持并不完美。 为此,将副本放入 .sc/plugins/ 中。 然后,在 $HOME/.scrc 中添加一行,内容如下:

plugin "cln" = "c.py"

现在,每当你使用 G(表示 get)在 scn 中打开扩展名为 .cln 的文件时,它都会通过 c.py 进行过滤,并且 sc 将从插件的标准输出中获取其输入。 不幸的是,这种支持显然很少使用,并且实现得不好。 在命令行上指定 .cln 文件(sc r.cln)不会调用插件,因此你必须在不带文件的情况下启动 sc,并使用 G 命令加载文件。 此外,如果你稍后保存文件,它将使用 r.cln 作为默认文件名,但保存 sc 格式文件。 因此,如果你使用插件格式,你还需要指定一个相应的 plugout 脚本(我们称之为 cout.py),并在 $HOME/.scrc 中添加一行,内容如下:

plugout "cln" = "cout.py"
高级用法

sc 还有一些其他简洁的功能。 例如,它可以支持电子表格文件的自动加密。 但是,Ubuntu 包未编译该支持,并且在编译带有该支持的版本时,很明显,一段时间以来没有人尝试过它,因为它需要一些修补。 为了支持加密,sc 只是通过 /usr/bin/crypt 传递输出文件,当你 (P)ut 文件时,它会要求输入密码。 因此,我更喜欢在 eCryptfs 文件系统(以及加密的交换空间)中的目录中使用 sc,这样我生成的所有文件都会被加密。

sc 还支持彩色单元格。 你可以变得非常花哨,并使用 sc 支持的任何函数计算前景色和背景色——这意味着单元格值、行和列、一天中的时间甚至外部函数(见下文)都可以确定单元格颜色。 通过输入以下内容告诉 sc 开始使用颜色:^T-C(Ctrl-T,表示切换,后跟 C,表示颜色)。 如果你在此之后保存工作表,则将保存命令“set color”,并且工作表将加载颜色。 有八个颜色对,你可以使用 C 定义其前景色和背景色值。 例如,输入C后跟color 1 = @red;@black,它将颜色 1 定义为前景色红色,背景色黑色。 默认颜色组合显示在 sc man 页面中。

你可以通过几种简单的方式使用这些颜色。 如果你输入^T-N,则具有负值的单元格的颜色值将递增 1——例如,如果单元格原本为颜色 3,则将以颜色 4 显示。 如果你输入^T-E,则具有错误值的单元格将以颜色 3 显示。 要将颜色 4 分配给范围 A0:D5,请输入rC(范围颜色),后跟A0:D5 4。 最后,要查看你分配给单元格的颜色,请输入rS.

sc 中提供了大量函数,但如果你发现你需要更奇特的东西,你可以在 C、Python 或任何你喜欢的语言中实现它们,并将它们用作外部函数。 输入^Te以启用外部函数。 然后,编写你的函数,使其从标准输入获取输入并将输出发送到标准输出。 例如,将以下内容放入名为 bci.sh 的文件中

#!/bin/sh
echo $* | bc -ql

并使其可执行

chmod ugo+x bci.sh

现在在 sc 中,在 A0 和 B0 中输入值,然后将 C0 设置为@ston(@ext("./bci.sh",A0+B0))。 @ston 函数会将 bci.sh 返回的字符串转换为数字。

我自己没有遇到过这种情况,但是可以想象,在足够大的电子表格中使用足够多的外部函数,重新计算可能会开始明显减慢速度。 在这种情况下,你可以通过输入以下内容来停止自动重新计算:^T-a。 之后,只有在你按 @ 时,工作表才会重新计算。

与外部函数类似,sc 也支持简单和高级宏。 简单宏是一个包含常规 sc 命令的文本文件。 你可以通过输入 R 来运行它,或者通过使用 A 来要求它在每次加载文件时自动运行。 高级宏是可执行文件,它们通过管道与 sc 通信。 这样,它们实际上可以从 sc 请求信息。 你可以通过输入 R,然后在文件名之前加上 | 来调用高级宏。 我见过的唯一像样的文档是源代码中包含的 SC.MACROS 文件。 以下宏是高级宏的简单(且无用)示例。 将以下内容放入文件 $HOME/.sc/macros/down.sh 中,并使其可执行

#!/bin/bash
echo down

启动 sc,然后输入R(运行)|~/.sc/macros/down.sh。 请注意,文件名之前的 | 表示这是一个高级宏。 当你运行此宏时,光标将向下移动一个单元格。 换句话说,sc 读取 echo 命令的“down”输出,并将其作为命令执行(有关你可以使用的命令列表,请参阅 SC.MACROS)。

如果你将要使用大量宏,你可能希望使用 D 命令定义 sc 应该在其中搜索宏的路径。 你还可以定义一个功能键来运行常用的宏。 例如,将以下内容添加到你的 .scrc 中,以使 F2 调用 down.sh 宏

fkey 2 = "merge \"|~/.sc/macros/down.sh\""

现在,你再也不需要输入 j 了!

还有更多功能,就像本节中列出的功能一样,我自己不太使用,但我可以看到它们可能很有用。 你可以切换^T-$以使所有数值都被解释为美分。 而且,你可以配置换行符操作,这样,当你输入值时,当你输入最后一列时,你会自动移动到下一行的第一个单元格。 对我来说,这些都属于需要更多思考才能弄清楚是否以及如何使用它们的类别,而不是仅仅使用默认值,所以我没有使用它们,尽管我一直想尝试最后一个。 man 页面和帮助页面可以向你指出更多内容,并且它们可能值得一看,看看你会发现哪些内容有用。

结论

Linux 用户有很多电子表格的选择,更不用说基于 Web 的电子表格了,包括 Google Docs 电子表格。 但是,如果有人被问及可以在终端中使用的电子表格,大多数人可能会感到困惑。 sc 是最古老的 FOSS 电子表格之一。 它已经可用超过 20 年,并且它是基于终端的,其按键绑定对于任何 vi 用户来说都应该很熟悉。 它支持高级宏、插件和外部函数,并且可以导出为其自己的格式、纯文本、LaTeX 或 CSV,以便轻松输入到其他电子表格中。

Serge Hallyn 是 Canonical 的 Linux 开发人员。 多年来,他一直参与容器、SELinux 和 POSIX 功能。

加载 Disqus 评论