検索結果ファイル¶
扱うこと: work/search_results.txt の出力フォーマット、ヒット 1 行の組み立て、ヒットから元のファイル名・場所・行番号を求める方法。扱わないこと: 検索の仕様そのもの(検索)。先に読むページ: 検索、インデックスのファイルの形。
出力フォーマット(work/search_results.txt)¶
画面の[結果をファイルに出力]で、表示中の結果(絞り込み後)を書き出す。UTF-8(BOM 付き)、改行は CRLF。
【検索文字列 <ワード>】 <件数> 件
ファイル名<TAB>場所<TAB>種別<TAB>行<TAB>A<TAB>B<TAB>…(該当行の最大セル数分の列名)
<相対フォルダ\><ファイル名><TAB><場所><TAB><種別><TAB><行番号><TAB><該当行>
...
【検索文字列 …】の空白は全角スペース。ブロックの後に空行を 1 行出力する。- ファイル名は、インデックスフォルダからの相対フォルダ(= クロール対象フォルダからの相対フォルダ)付き。直下のファイルはフォルダ部分なし。
- 場所・種別 は、ヒットの
Location(場所の名前。本文インデックスのメタ情報から組み立てる。ファイル名・場所の求め方)を場所ごとの表記にしたもの(describePlace。画面の見出しの要約と同じ)。結果の表の「場所」列は、Excel ではこれにセル番地を足した行ごとの表記(describeHitPlace。[シート]売上!B12)を出すが、この出力にはセル番地を付けない。
場所の名前(Location) |
場所 | 種別 |
|---|---|---|
売上(Excel のシート) |
[シート]売上 |
セル |
売上[図形] |
[シート]売上 |
図形 |
売上[コメント] |
[シート]売上 |
コメント |
売上[ヘッダー・フッター] |
[シート]売上 |
ヘッダー・フッター |
ページ003(Word) |
3 ページ(目安) |
本文 |
ページ003[図形] ページ003[コメント] |
3 ページ(目安) |
図形 / コメント |
文書[コメント](本文に参照の無い Word のコメント) |
文書 |
コメント |
スライド002[図形] スライド002[コメント] |
スライド 2 |
図形 / コメント |
ヘッダー・フッター 脚注 |
ヘッダー・フッター 脚注 |
本文 |
スライド002(非表示)(PowerPoint) |
スライド 2(非表示) |
本文 |
スライド002_ノート |
スライド 2 |
ノート |
本文(テキストファイル。場所は 1 つだけ) |
(空) | 本文 |
- Word のページは、Word が保存したときのページ区切りから数えた目安のため「(目安)」を付ける(Word・既知の問題)。
- Excel の図形・コメントは、該当行の 1 列目が図形の左上・コメントのセル番地、2 列目が文字(Excel の図形・コメントの読み取り)。Excel のヘッダー・フッターは、該当行が文字だけ(セル番地の列は無い。行番号はその場所の中の何行目か)。
- シート名にタブ・改行が入っている場合(Excel は付けられる)は、列・行が分かれないようスペースにする。
- 行番号 は場所の中の行番号(
searchContentIndexのLineNumber。元の TSV の行番号と同じ)。Excel ではシートの行番号、Word・PowerPoint では場所(ページ・スライド等)の中で何行目か。 - 該当行 は、結果をすべて選択して Excel に貼り付けたとき、5 列目以降に元の列の順(5 列目 = A 列)でセルが並ぶように出力する。見出しの列名(A, B, C…)と行番号で、元のセル位置が分かる。
- Excel: TSV の行をそのまま出力し、セル内改行(U+2028)だけを LF に戻す。改行を含むセルは Excel の出力時点で
"で囲まれているため、貼り付けても 1 セル内の改行となり、右隣のセル・後続の行はずれない。このため結果ファイルをテキストエディタで開くと、改行を含むセルは複数行に見える。 - Word・PowerPoint: 行(段落、または表の 1 行をタブ区切りにしたもの)は
"で囲まれていない。Excel は"で始まるセルを囲みの"と解釈して後続がずれるため、"で始まるセルだけを"で囲み、中の"を""にする。途中に"を含むセルはそのままで、貼り付けても文字どおりになる。 - 見出しの列名の数は、ヒット行を Excel に貼り付けたときの最大セル数(
countTsvFields。"で始まるセルは閉じる"までを 1 セルとする)。ヒットが 0 件のときはファイル名<TAB>場所<TAB>種別<TAB>行と件数の見出し 2 行のみとなる。 - 画面の[コピー]も同じ形式(
toSearchResultLines)でクリップボードに入れる。
出力例(⏎ はセル内改行の LF):
【検索文字列 りんご】 3 件
ファイル名 場所 種別 行 A B C D
sub dir\old.xls [シート]Sheet1 セル 3 古い形式 りんご
見積[確定].xlsx [シート]一覧 セル 12 りんご 100 "青森産⏎ふじ"
報告書.docx 2 ページ(目安) 本文 5 """りんご""の出荷"
1 行の組み立て¶
flowchart LR
H["searchContentIndex のヒット<br>(RelDir, Book, Location, LineNumber, Line)"] --> T["toResultLine<br>ヒットのファイル名(Book)・場所(Location)"]
T --> X{"Excel のインデックス?<br>(.xls? のファイル)"}
X -- はい --> XL["U+2028 → LF"]
X -- いいえ --> WD["#quot; で始まるセルを #quot; で囲む"]
XL --> J{"フォルダ部分(RelDir)がある?"}
WD --> J
J -- はい --> O1["フォルダ\ファイル名 TAB 場所 TAB 種別 TAB 行番号 TAB 該当行"]
J -- いいえ --> O2["ファイル名 TAB 場所 TAB 種別 TAB 行番号 TAB 該当行"]
ファイル名・場所の求め方(readContentIndexPlaces)¶
ヒット 1 件の元のファイル名(Book)・場所(Location: シート名・ページ・スライド)・元のファイルのあるフォルダ(RelDir)は、次のように求める。
| 値 | 求め方 |
|---|---|
| RelDir | 本文インデックスのファイルのあるフォルダの、インデックスのフォルダ(Root)からの相対パス(findContentIndexFiles) |
| Book | 一致した位置より前の、いちばん近い ファイル名= の値 |
| Location | 一致した位置を含む場所のメタ情報(シート / ページ / スライド / 部分・対象・非表示)から組み立てた場所の名前(convertContentIndexMetaToPlace。見積[図形]・ページ001・スライド002(非表示)・スライド001_ノート など。インデックスのファイルの形「本文インデックスの形式」) |
| LineNumber | 場所の中身の先頭から数えた行番号(場所のメタ情報の後の最初の行が 1) |
flowchart TD
A["本文インデックスの全文"] --> B["readContentIndexPlaces<br>先頭が RS の行(メタ情報)を順に読む"]
B --> C["ファイル名= で元のファイルが変わる<br>シート= / ページ= / スライド= / 部分= で場所が変わる"]
C --> D["場所ごとの一覧<br>(Book, Location, 中身の先頭の位置, 終わりの位置)"]
D --> E["一致の位置を含む場所を探し、<br>場所の先頭から改行を数えて行番号にする"]
- 書き換えたインデックスで偽の名前を開かせないため、
ファイル名=の値がtestSourceBookName(取り込み対象の拡張子であり、区切り・制御文字などを含まない名前)を通らない場所は、一覧に入れない(その場所の一致は結果に出ない)。 - 場所の一覧は、全文で一致したとき(と、読んだ内容を使い回すために残すとき)だけ作る。一致しない本文インデックスのファイルでは作らない(検索を速くする仕組み)。
- 場所の番号(
ページ・スライド)が数でないときは、その値の文字列をそのまま場所の名前にする(例外にしない)。 - 本文インデックスのファイルの読み取り(読む・場所の一覧を作る・照合する)で例外になったファイル(版が違う・版が無い・形が崩れている・読めない)と、大きさが
contentIndexSearchMaxBytes(64MB)を超えるファイル(読まずに飛ばす)は、そのファイルだけ飛ばし、ほかのファイルの検索を続ける。飛ばしたファイルは検索の結果のSkipped(パスの一覧)に入り、検索が終わったステータスバーの文の後ろに読めなかったインデックスのファイル:N 件(getSkippedContentIndexText)と出る。検索の全体を「検索できませんでした」にはしない。件数の上限で打ち切ったときは、そこまでに読んだファイルの分だけが入る。照合の時間切れは検索語の問題のため、飛ばさずに検索の全体を中止する。読んだ内容を使い回さないとき(画面は使い回す)は、語に一致しないファイルは場所の一覧を作らないので、そのファイルが壊れていても飛ばした数には入らない。 - 画面の選択行のプレビュー(
readContentIndexLines)も同じ一覧で、Book・Location が一致する場所の中から前後の行を取り出す(検索タブ 選択行のプレビュー)。 - 検索では TSV の相対パスを分解しない。TSV の名前(フォルダ名 = 元のファイル名、ファイル名 = 場所)は、本文インデックスに入れるとき(
getIndexFolderBooks)だけに使う。
場所の付け方は インデックス作成 の インデックスのファイルの形・場所の符号化 を参照。
長い行を切る¶
テキストファイル(.txt 等)は、1 行に数 MB の内容が入ることがある(.json .xml .log など)。取り込み・検索の一致そのものは行を切らずに行う(行番号と検索の一致がずれないため)が、結果の表・プレビュー・この検索結果ファイル・画面の[コピー]に出す行は、search_query.ps1 の truncateHitLine で ${hitLineMaxChars}(1,000 文字)に切る。
- 一致した行(結果の表・検索結果ファイル)は、一致の位置の
${hitLineBeforeMatchChars}(200)文字前から 1,000 文字を取る(一致の位置が分からない図形・コメント等では先頭から)。 - 選択行のプレビューの前後の行(
readContentIndexLines)は、一致していないため常に先頭から 1,000 文字を取る。 - 切った側に
…を付ける(先頭・末尾のどちらか、または両方)。 - Excel・Word・PowerPoint の行は切らない(Excel は列の位置がずれるため。詳細は テキストファイルの読み取り)。
content_index_search.ps1のsearchContentIndexFilesは、元のファイル名の拡張子(getContentIndexFileKind)がテキストのときだけ切る。