如何在大型文件中生成自动索引(索引)?

如何在大型文件中生成自动索引(索引)?

我想通过输入一个大文件(1189 章,31'171 节/句子)来生成索引

如果可以的话

  • 最小字长限制
  • 限制排除特定词语

输入文件:直接下载链接txt文件

原始下载链接压缩文件夹

1 Mose 1
1 ¶ Im Anfang schuf Gott den Himmel und die Erde.
2  Und die Erde war wüst und leer, und es lag Finsternis auf der Tiefe, und der Geist Gottes schwebte über den Wassern.
3 ¶ Und Gott sprach: Es werde Licht! Und es ward Licht.
4  Und Gott sah, daß das Licht gut war; da schied Gott das Licht von der Finsternis;
5  und Gott nannte das Licht Tag, und die Finsternis Nacht. Und es ward Abend, und es ward Morgen: der erste Tag.
6 ¶ Und Gott sprach: Es soll eine Feste entstehen inmitten der Wasser, die bilde eine Scheidewand zwischen den Gewässern!
7  Und Gott machte die Feste und schied das Wasser unter der Feste von dem Wasser über der Feste, daß es so ward.
8  Und Gott nannte die Feste Himmel. Und es ward Abend, und es ward Morgen: der zweite Tag.
9 ¶ Und Gott sprach: Es sammle sich das Wasser unter dem Himmel an einen Ort, daß man das Trockene sehe! Und es geschah also.
10  Und Gott nannte das Trockene Land; aber die Sammlung der Wasser nannte er Meer. Und Gott sah, daß es gut war.
11  Und Gott sprach: Es lasse die Erde grünes Gras sprossen und Gewächs, das Samen trägt, fruchtbare Bäume, deren jeder seine besondere Art Früchte bringt, in welcher ihr Same sei auf Erden! Und es geschah also.
12  Und die Erde brachte hervor Gras und Gewächs, das Samen trägt nach seiner Art, und Bäume, welche Früchte bringen, in welchen ihr Same ist nach ihrer Art. Und Gott sah, daß es gut war.
13  Und es ward Abend, und es ward Morgen: der dritte Tag.
14 ¶ Und Gott sprach: Es seien Lichter an der Himmelsfeste, zur Unterscheidung von Tag und Nacht, die sollen zur Bestimmung der Zeiten und der Tage und Jahre dienen,
15  und zu Leuchtern an der Himmelsfeste, daß sie die Erde beleuchten! Und es geschah also.
16  Und Gott machte die zwei großen Lichter, das große Licht zur Beherrschung des Tages und das kleinere Licht zur Beherrschung der Nacht; dazu die Sterne.
17  Und Gott setzte sie an die Himmelsfeste, damit sie die Erde beleuchteten
18  und den Tag und die Nacht beherrschten und Licht und Finsternis unterschieden. Und Gott sah, daß es gut war.
19  Und es ward Abend, und es ward Morgen: der vierte Tag.
20 ¶ Und Gott sprach: Das Wasser soll wimmeln von einer Fülle lebendiger Wesen, und es sollen Vögel fliegen über die Erde, an der Himmelsfeste dahin!
21  Und Gott schuf die großen Fische und alles, was da lebt und webt, wovon das Wasser wimmelt, nach ihren Gattungen, dazu allerlei Vögel nach ihren Gattungen. Und Gott sah, daß es gut war.
22  Und Gott segnete sie und sprach: Seid fruchtbar und mehret euch und füllet das Wasser im Meere, und das Geflügel mehre sich auf Erden!
23  Und es ward Abend, und es ward Morgen: der fünfte Tag.
24 ¶ Und Gott sprach: Die Erde bringe hervor lebendige Wesen nach ihrer Art, Vieh, Gewürm und Tiere des Feldes nach ihrer Art! Und es geschah also.
25  Und Gott machte die Tiere des Feldes nach ihrer Art und das Vieh nach seiner Art. Und Gott sah, daß es gut war.
26 ¶ Und Gott sprach: Wir wollen Menschen machen nach unserm Bild uns ähnlich; die sollen herrschen über die Fische im Meer und über die Vögel des Himmels und über das Vieh auf der ganzen Erde, auch über alles, was auf Erden kriecht!
27  Und Gott schuf den Menschen ihm zum Bilde, zum Bilde Gottes schuf er ihn; männlich und weiblich schuf er sie.
28  Und Gott segnete sie und sprach zu ihnen: Seid fruchtbar und mehret euch und füllet die Erde und machet sie euch untertan und herrschet über die Fische im Meer und über die Vögel des Himmels und über alles Lebendige, was auf Erden kriecht!
29 ¶ Und Gott sprach: Siehe, ich habe euch alles Gewächs auf Erden gegeben, das Samen trägt, auch alle Bäume, an welchen Früchte sind, die Samen tragen; sie sollen euch zur Nahrung dienen;
30  aber allen Tieren der Erde und allen Vögeln des Himmels und allem, was auf Erden kriecht, allem, was eine lebendige Seele hat, habe ich alles grüne Kraut zur Nahrung gegeben. Und es geschah also.
31 ¶ Und Gott sah an alles, was er gemacht hatte, und siehe, es war sehr gut. Und es ward Abend, und es ward Morgen: der sechste Tag.

1 Mose 2
1 ¶ Also waren Himmel und Erde vollendet samt ihrem ganzen Heer,
2  so daß Gott am siebenten Tage sein Werk vollendet hatte, das er gemacht; und er ruhte am siebenten Tage von allen seinen Werken, die er gemacht hatte.
3  Und Gott segnete den siebenten Tag und heiligte ihn, denn an demselbigen ruhte er von all seinem Werk, das Gott schuf, als er es machte.
4 ¶ Dies ist die Entstehung des Himmels und der Erde, zur Zeit, als Gott der HERR Himmel und Erde schuf.
5  Es war aber noch kein Strauch des Feldes auf Erden, noch irgend ein grünes Kraut auf dem Felde gewachsen; denn Gott der HERR hatte noch nicht regnen lassen auf Erden, und es war kein Mensch vorhanden, um das Land zu bebauen.
6  Aber ein Dunst stieg auf von der Erde und befeuchtete die ganze Erdoberfläche.

\排除{单词=Aaron}

输出文件看起来应该像这样:

Abend   1 Mose 1,5; 1 Mose 1,8; 
        1 Mose 1,13; 1 Mose 1,19; 
        1 Mose 1,23; 1 Mose 1,31; 
        1 Mose 3,8; ….; 3 Mose 24,3; 
        …; Matthäus 14,15; …
Aber    1 Mose 8,9; 1 Mose 8,20;

在示例中,我限制了列宽,因此可以打印包含多列的纸张(我可能更喜欢 4 列)。

我查阅过类似网页http://www.mrunix.de/forums/archive/index.php/t-54191.html找到解决方案,但没有得到我想要的结果。

有没有简单的方法来生成这个索引?

如果有人知道 stackexchange 内一个更适合我的要求的 python 或 php 论坛,也请告诉我。

作为对一条评论的回复,如果索引中的条目按以下顺序按字母顺序排列,我会非常高兴。

1. Mose
2. Mose
3. Mose
4. Mose
5. Mose
Josua
Richter
Ruth
1. Samuel
2. Samuel
1. Könige
2. Könige
1. Chronik
2. Chronik
Esra
Nehemia
Esther
Hiob
Psalmen
Sprüche
Prediger
Hohelied
Jesaja
Jeremia
Klagelieder
Hesekiel
Daniel
Hosea
Joel
Amos
Obadja
Jona
Micha
Nahum
Habakuk
Zephanja
Haggai
Sacharja
Maleachi
Matthäus
Markus
Lukas
Johannes
Apostelgeschichte
Römer
1. Korinther
2. Korinther
Galater
Epheser
Philipper
Kolosser
1. Thessalonicher
2. Thessalonicher
1. Timotheus
2. Timotheus
Titus
Philemon
Hebräer
Jakobus
1. Petrus
2. Petrus
1. Johannes
2. Johannes
3. Johannes
Judas
Offenbarung

没有章节的书籍如下

Obadja
Philemon
2. Johannes
3. Johannes
Judas

如果更容易的话,我可以在输入文件中添加数字 1,用于没有章节的书籍(例如 Objada > Objada 1)...如果将一致性按代码部分中的顺序进行排序需要大量工作,那么按字母顺序进行排序也是可以的......

在得到第一个答案之前我忘了说,我只想使用免费提供的软件(没有共享软件)。

输出文件应如下所示: http://www.gurt-der-wahrheit.org/files/konkordanz_schlachter_1951_A4.pdf

答案1

输出文件应如下所示:http://www.gurt-der-wahrheit.org/files/konkordanz_schlachter_1951_A4.pdf

当然可以。这样如何?

example page 2

完整的索引(以上为第 2 页)由以下文件生成(使用lualatex而不是进行编译pdflatex):

\documentclass[a4paper]{article}
\usepackage{luatex85} % a4paper doesn't seem to take effect otherwise
\usepackage[margin=1cm, top=0.5cm, footskip=0.5cm]{geometry}
\usepackage{fontspec}
\setmainfont{Arial}

\begin{document}
\parindent=0pt \twocolumn \scriptsize
\pretolerance=-1 \sloppy  % Skip the first pass, and avoid overfull boxes
\spaceskip=\fontdimen2\font plus 2\fontdimen3\font minus \fontdimen4\font % Fewer underfull warnings, by allowing more stretch
\directlua{dofile('concordance.lua')}
\directlua{words, locations = concordance('bibschl.txt', 'latin1')}
\directlua{printConcordance(words, locations, {minLength=2, otherExclusions={'Aaron','RECHT','zorn'}})}
\end{document}

其中concordance.lua,生成索引(对于每个单词,找到它出现的所有位置)并排版各个条目(粗体键、用分号分隔位置等):

function concordance(filename, encoding)
   -- Given a file that has the following structure:
   --         <blank line>
   --         BookName<space>ChapterNumber
   --         VerseNumber<space>Verse
   --         VerseNumber<space>Verse
   --         ...
   --         <blank line>
   --         BookName<space>ChapterNumber
   --         ...
   -- (Each verse itself is a sequence of space-separated words, ignoring case and trailing punctuation.)
   -- Returns two tables: (1) the words, in sorted order, and (2) mapping words to locations (book, chapter, verse)
   local readBookNext = true  -- Whether the *next* line contains Book & Chapter
   local currentBook = ''
   local currentChapter = 0
   local concordanceTable = {}
   for line in io.lines(filename) do
      line = makeUTF8(line, encoding)  -- Just in case encoding='latin1'
      if line == '' then readBookNext = true
      elseif readBookNext then
         currentBook, currentChapter = string.match(line, '^(.*) ([0-9]*)$')
         readBookNext = false
      else
         verseNumber, verse = string.match(line, '^([0-9]*) (.*)$')
         for word in string.gmatch(verse, '%S+') do
            addWordToConcordance(word, currentBook, currentChapter, verseNumber, concordanceTable)
         end
      end
   end
   local keys = {}
   for word, _ in pairs(concordanceTable) do table.insert(keys, word) end
   table.sort(keys)
   return keys, concordanceTable
end

local badFirsts = {['¶'] = true, ['«'] = true, ['-'] = true, ['<']=true, ['(']=true, [',']=true}
local badLasts = {['.']=true, [',']=true, [':']=true, ['!']=true, [';']=true, ['?']=true, ['»']=true, [')']=true, ["'"]=true, ['>']=true, ['`']=true}
function addWordToConcordance(origWord, book, chapter, verse, concordanceTable)
   -- In `concordanceTable`, adds (book, chapter, verse) to the entry for word
   local word = unicode.utf8.upper(origWord)
   while badFirsts[unicode.utf8.sub(word, 1, 1)] do word = unicode.utf8.sub(word, 2) end  -- Strip leading punctuation
   while badLasts[unicode.utf8.sub(word, -1)] do word = unicode.utf8.sub(word, 1, -2) end -- Strip trailing punctuation
   if string.match(word, '^[0-9-]*B?$') then return end  -- Ignore empty words and words like "42-3" or "29-39B"
   local list = concordanceTable[word] or {}
   table.insert(list, {book=book, chapter=chapter, verse=verse})
   concordanceTable[word] = list
end

function makeUTF8(line, encoding)
   -- Converts text `line` from latin1 (ISO-8859-1) to UTF-8, if necessary.
   if encoding == 'utf8' or encoding == nil then
      return line
   elseif encoding == 'latin1' then
      local utf8Line = ''
      for c in string.gmatch(line, '.') do utf8Line = utf8Line .. unicode.utf8.char(string.byte(c)) end
      return utf8Line
   else
      error(string.format('Unknown encoding "%s"', encoding))
   end
end

--------------------------------------------------------------------------------
-- Above are functions that generate the concordance; below are functions for injecting that into TeX
--------------------------------------------------------------------------------
function printConcordance(words, locations, options)
   options = options or {}
   local includeThreshold = options['includeThreshold'] or 300 -- Words that occur too often are dropped
   local breakThreshold = options['breakThreshold'] or 1000    -- A "paragraph" break is added after enough entries
   local minLength = options['minLength'] or 1                 -- Words shorter than this length are dropped
   local otherExclusions = {}                                  -- Words in this table are dropped
   for _, ex in ipairs(options['otherExclusions'] or {}) do
      otherExclusions[unicode.utf8.upper(ex)] = true
   end
   local numPrinted = breakThreshold + 100  -- more than breakThreshold: we want a “break” before the first word
   for _, word in ipairs(words) do
      tex.print([[\hskip 1.5\fontdimen2\font plus 5\fontdimen3\font minus \fontdimen4\font]])
      local n = #locations[word]
      if n > includeThreshold then
         print(string.format('Dropping word %s (occurs %d times)', word, n))
      elseif unicode.utf8.len(word) < minLength then
         print(string.format('Dropping word %s (its length %d is less than %d)', word, unicode.utf8.len(word), minLength))
      elseif otherExclusions[word] ~= nil then
         print(string.format('Dropping word %s (it was specified as an exclusion)', word))
      else
         if numPrinted > breakThreshold then
            tex.print(string.format([[\par\underline{\textbf{%s}}\par]], word))
            numPrinted = 0
         else
            tex.print(string.format([[\textbf{%s}]], word))
         end
         numPrinted = numPrinted + n
         for i, v in ipairs(locations[word]) do
            if i > 1 then tex.sprint('; ') end
            tex.sprint(string.format('%s%s:%s', abbrev(v.book), v.chapter, v.verse))
         end
      end
   end
end

-- Abbreviations that aren't just first 3 letters
local knownBooks = {Richter='Ri', Ruth='Rt', Hiob='Hi', Psalmen='Ps', Hohelied='Hld', Klagelieder='Klg',
                    Amos='Am', Zephania='Zef', Matthäus='Mt', Lukas='Lk', Apostelgeschichte='Apg', Philemon='Phm'}
function abbrev(book)
   if knownBooks[book] ~= nil then return knownBooks[book] end
   -- First 3 letters, but if 2nd letter is a space then ignore it.
   if string.sub(book, 2, 2) == ' ' then
      knownBooks[book] = unicode.utf8.sub(book, 1, 1) .. unicode.utf8.sub(book, 3, 4)
   else
      knownBooks[book] = unicode.utf8.sub(book, 1, 3)
   end
   return knownBooks[book]
end

要更改 TeX 所看到的内容,您可以更改该printConcordance函数。它有一个options参数,您可以通过它控制各种事物:

  • includeThreshold用于删除出现频率过高的单词。(例如,“UND”出现了 42000 多次,您肯定不想对它进行索引;那么出现了 862 次的“DAVID”呢?)默认阈值设置为 300 次。
  • minLength对于问题中提到的“最小字长限制”
  • otherExclusions对于问题中提到的“限制排除特定的词语”。

当然,您可以自己编辑该函数以进一步更改行为。编译上述文件时,终端输出将告诉您删除了哪些单词以及原因。在我的笔记本电脑上,生成索引大约需要 5 秒钟,排版大约需要 25 秒钟,因此整个运行总共需要大约 30 秒。

答案2

由于您要求提供其他程序的链接,因此有一个解决方案,尽管是商业解决方案。首先,使用 LaTeX 创建 PDF 文件。其次,通过 PDF Index Generator 运行该文件:https://www.pdfindexgenerator.com/。您将能够修改单词列表以删除常用单词。然后您将获得一个文件,您可以将其附加到 LaTeX 生成的 PDF 中。需要注意的是,生成的列表的格式(即字体和样式)与 LaTeX 生成的文本不同。要实现这一点,您必须从 PDF 中提取索引文本,然后将其附加到 LaTeX 生成的文本中。除了作为用户之外,我与 PDF Generator 没有任何关系。

您可以在以下位置找到德语和其他语言的常用词或“停用词”的免费列表:https://github.com/Alir3z4/stop-words

相关内容