挖掘純文字

挖掘純文字

(原標題:grep 根據段落而不是行)

這個問題的動機是fzf,它允許我在我的巨大文件系統中找到某個文件模糊地、增量地,提供非常非常快速的搜尋體驗(在此查看大量可愛的 gif 動圖)文章)。

我的想法是在我的筆記上做類似的事情。我有一堆純文字格式的轉瞬即逝的筆記、日記、備忘錄等。為了可讀性,每行包含不超過 72 個字元。這使得我的筆記很難被搜索,因為我對現有搜索工具的天真了解,例如grepripgrep..

現在,您可以顯示 (更多的/較少的)圍繞著匹配模式的上下文,但這不是我想要的。這裡我舉一個例子來使它更準確。

1  Victim mentality is an acquired personality trait in which a person
2  tends to recognize or consider themselves as a victim of the negative
3  actions of others, and to behave as if this were the case in the face
4  of contrary evidence of such circumstances. Victim mentality depends
5  on clear thought processes and attribution.
6
7  (from wikipedia: Victim mentality)

假設我半年前記下了這張紙條,並且我知道它在我的文件系統中的某個位置。像往常一樣,我們無法背誦確切的單詞,但是我們記得上下文!在我的檔案系統上輸入諸如、、 或 之grep類的文字可能會給我personalityclear thoughtvictim許多相關的事情讓我真正縮小範圍。

應該有一個工具(無論是否存在)可以幫助搜尋這樣的文字。我們的舊筆記(純文字)將更有價值。有沒有辦法和我們的好老朋友grep及其親戚一起做呢?或者有其他可行的方法嗎?任何意見也受到高度讚賞。

答案1

讓我們將(搜尋)過程分成更小的部分。

首先,我們需要取得要搜尋的文件列表,例如當前目錄 ( .) 中所有帶有 txt 副檔名 ( -name "*.txt") 的文件,這些文件肯定是文件 ( -type f):

find . -name "*.txt" -type f

此結果可以用作在這些檔案內部grep尋找的輸入something,包括輸出中的行號和檔案名,忽略大小寫 ( -nHi),+最後確保所有檔案在一次執行中都被 grep 出來(一次不是一個):

find . -name "*.txt" -type f -exec grep -nHi 'something' {} +

如果檔案數太大 (> $ARG_MAX),您應該替換+\;

上一個命令的輸出類似:

./some/dir/somewhere/songs.txt:128:But had me believing it was always something that I'd done
./some/dir/somewhere/songs.txt:883:Was never something I pursued
./some/dir/somewhere/songs.txt:2905:I know something about love 
./some/dir/somewhere/songs_other.txt:11780:will come across something like this:  F (Dshape).

因此,如果將這些行拆分,:您將獲得 3 個組成部分:檔案名稱、找到匹配項的行號以及行本身。

現在,如果您為每個匹配的文件保留此信息,則可以搜索下一個術語並求和匹配距離以查找搜索術語最近的文件。

對於您的範例文本,如果您搜尋 3 個術語(personalityclear thoughtvictim),您會得到相應的行號為 1、5 和 2,因此該文件的距離是(源自第一個術語)

abs(1-5) + abs(1-2) = 5 

因此,您可以根據包含所有術語並使它們在該文件中最接近的方式對文件進行排序。

當然,這並不是全部,例如某些文件多次包含相同的術語,而且該演算法必須做出一些決定如何計算距離,但我認為以上是開始的事情。

答案2

一個簡單的 Perl 語句就可以完成這項工作。如果檔案中存在所有關鍵字(即 和 ),下列personality指令將列印檔名,後面接著「found」。clear thoughtvictim

perl -0777 -ane 'print "$ARGV: found\n" if /^(?=.*personality)(?=.*clear thought)(?=.*victim)/s' file.txt 

輸出:

file.txt: found

解釋:

-0777       # slurp mode
-ane        # read the file ans execute the following
print "$ARGV: found\n"      # print,$ARGV contains the current filename
if                          # if
  /                         # regex delimiter
    ^                       # begining of file
      (?=.*personality)     # positive lookahead, make sure we have "personality"
      (?=.*clear thought)   # positive lookahead, make sure we have "clear thought"
      (?=.*victim)          # positive lookahead, make sure we have "victim"
  /s                        # regex delimiter, s = dot matches newline

如果要搜尋所有txt文件,請使用perl ...... *.txt

相關內容