我有一个物理课讲座主题的文本文件,如下所示:
1/14,Galilean relativity,Einsteinian relativity,Minkowski space,Henri Poincare,,
1/16,Lorentz transformations,Velocity transformations,Proper time,Light aberration,Lorentz tensors formalism,Minkowski space
1/23,Lorentz boost,Lorentz group,Poincare group,contravariant tensor,covariant tensor,d'Alembertian
我实际上将其存储为 Google Doc,因此我可以将其导出为 tsv、ods、xslx 等,而不是 csv。
我想生成一个像书后面那样的索引,按日期字母顺序列出主题,例如
d'Albertian 1/23
... (more entries)
Minkowski space 1/14 1/16
... (more entries)
Velocity transformations 1/16
或者如果你想要更花哨一点:
d'Albertian ................. 1/23
... (more entries)
Minkowski space ............. 1/14, 1/16
... (more entries)
Velocity transformations .... 1/16
我首先想到的是使用LaTeX
,但索引包似乎都是按页码而不是日期之类的任意字符串进行索引。事实上,“MakeIndex 假设所有页码都是阿拉伯数字或小写罗马数字;”http://www.tex.ac.uk/ctan/indexing/makeindex/doc/makeindex.pdf。此外,的输入文件makeindex
必须是一个每行一个主题和页码的列表;它只进行排序和格式化:http://www.troubleshooters.com/linux/lyx/makeindex.htm
因此,我要找的软件需要执行以下操作:
- 接受 csv、tsv 或其他电子表格格式。这将是理想的,但我也可以接受可以相当容易地从电子表格文件生成的文本格式,例如通过替换
awk
或sed
。 - 将每行的第一个条目(例如日期
1/14
)与以下每个条目(例如主题Galilean relavity
、Minkowski space
等等)关联。 - 按字母顺序对所有日期的所有主题进行排序。
- 将多次出现的主题合并为一个条目,列出该主题出现的每个日期。
- 以标准格式输出结果。
我对该软件的唯一要求是它能在 Linux 上运行。
我对输出格式并不挑剔;文本文件、LaTeX、HTML、odf 等都可以,只要我能打印出纸质副本即可。
答案1
您反对 mono 吗?如果不反对,那么就使用 F# 交互吧
并使用以下 F# 脚本(您也可以编译它)
open System
open System.IO
let inputFile = "inputFile.csv"
let outputFile = "out.txt"
File.ReadAllLines(inputFile)
|> Seq.filter (fun i -> i.Length > 0)
|> Seq.collect
(fun i ->
let fields = i.Split(',')
let date = fields.[0]
fields.[1..] |> Array.map (fun entry -> date,entry)
)
|> Seq.groupBy snd
|> Seq.sortBy (fun (entry,_) -> entry.ToUpper())
|> Seq.filter (fun (entry,_) -> entry <> "")
|> Seq.map
(fun (entry,dates) ->
let dates = dates |> Seq.map fst |> Seq.sort
let datestr = String.Join (", ",dates)
String.Format("{0} ........ {1}", entry, datestr)
)
|> (fun i -> File.WriteAllLines(outputFile,i))
这将生成一个文本文件:
contravariant tensor ........ 1/23
covariant tensor ........ 1/23
d'Alembertian ........ 1/23
Einsteinian relativity ........ 1/14
Galilean relativity ........ 1/14
Henri Poincare ........ 1/14
Light aberration ........ 1/16
Lorentz boost ........ 1/23
Lorentz group ........ 1/23
Lorentz tensors formalism ........ 1/16
Lorentz transformations ........ 1/16
Minkowski space ........ 1/14, 1/16
Poincare group ........ 1/23
Proper time ........ 1/16
Velocity transformations ........ 1/16
虽然不是你想要的,但修改上述代码以生成 latex 标记会很容易。只需修改以下行
String.Format("{0} ........ {1}", entry, datestr)
为每行添加所需的标记。不幸的是,我现在无法访问 mono,因此使用 .NET 进行测试。
答案2
Shell 脚本和出色的awk
命令:
awk -F, '
{ for (i=2;i<=NF;i++) { subject_dates[$i]=subject_dates[$i] " " $1 } }
END { for (idx in subject_dates) { print idx, subject_dates[idx] } }
'
答案3
F#
和解决方案都awk
经过一些调整后效果很好。不过,我决定使用以下 Python 脚本:
#!/usr/bin/env python
import csv, sys
mydict = {}
for line in open(sys.argv[1],'r'):
tokens = line.strip().split(',')
item, keys = tokens[0], tokens[1:]
for key in keys:
if key != '':
# If the key is already in the dictionary,
# just add it to the set, otherwise make an
# empty set to add the item to.
mydict.setdefault(key, set()).add(item)
for key in sorted(mydict.keys(), key=str.lower):
print key + ' \dotfill ' + ', '.join(mydict[key])
在这种情况下,item
对应于日期,keys
对应于主题。\dotfill
是用点填充水平空间的 LaTeX 标记。