Grep

在文件中查找文本並複製到 csv

  • December 5, 2018

我需要提取一堆html文件中的文本(大約500K)要複製的文本看起來像<div class='cls '>text to be copied including some<span>and <p></p></span>and more text</div>

我決心(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)

我已經閱讀了有關如何使用 grep 執行此操作的其他問題,我認為該命令是

grep -r "/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" *.html > output.txt

它不起作用。我究竟做錯了什麼?

也試過pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" --file-list=fl.txt > output.txt- 它什麼都不做pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" > output.txt- 什麼都沒有

編輯1:嘗試以下格式的建議:

grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> touch output.txt
grep: -r: No such file or directory
grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> output.txt
grep: -r: No such file or directory
grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> output.txt
grep: -r: No such file or directory

grep -f "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" file111.html >> touch output.txt
grep: /(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/: No such file or directory

和其他一些排列,仍然沒有

不知道為什麼你添加了所有這些花里胡哨的東西。這個簡單的正則表達式對我有用:

grep "<div\sclass='cls\s'>.*<\/div>" file
<div class='cls '>text to be copied including some<span>and <p></p></span>and more text</div>

你有六個問題:

  1. 您包括/在正則表達式的開頭和結尾。您輸入、和其他程序進行搜尋,但您不需要它來搜尋。而且,實際上,只會在模式中包含文字字元。**/***regex***/**``sed``vi``grep``grep``/
  2. 要在 (plain) 中使用 PCRE grep,您必須使用-P.
  3. 沒有這樣的事情-regexp; 它必須是--regexp。或者—regexp=像在grep.

一旦我修復了上述錯誤,兩個命令 (grep -P和) 都可以正常工作——但它們列印了包含模式的整行,包括 . 之前或之後的pcregrep任何文本。<div …>``</div>

  1. 要僅列印與模式匹配的文本,您必須指定-o.

即使在我修復了它之後,我也得到了<div …>輸出(但不是 之前的文本<div …>,或者</div>之後的任何內容)。所以,

  1. 您的後視組有問題 - 它被包含在匹配中。

不幸的是,我對 PCRE 知之甚少,無法確切知道問題是什麼或如何解決它。幸運的是,我知道的足夠pcregrep多,知道一個解決方法。如果您的正則表達式中有多個擷取組, pcregrep讓您選擇要寫入輸出的擷取組。所以,我們可以pcregrep 通過將look-behind變成一個擷取組,然後忽略它來讓它起作用:

pcregrep -o **2** -r "(\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)"

但即使這樣也比它需要的更複雜。第一個 ( <div …>) 組不需要是擷取組;即,它根本不必是一個組。同樣,最後一個組(</div>前瞻組)根本不必是一個組。唯一需要成為一個組的是您要擷取的部分 -<div …>和之間的部分</div>

pcregrep **-o1** -r "\<div\sclass\=\'cls\s\'\>(.*)\<\/div\>"

請注意,我更改-o2-o1是因為現在只有一組。 

順便說一句,正如RudiC 發現的(但沒有提到),這些反斜杠幾乎都不是必需的。AFAICT,您唯一需要的是\s字元串中的那些;所以我們可以將上面的內容簡化為:

pcregrep -o1 -r "<div\sclass='cls\s'>(.*)</div>"

現在我們已經消除了正則表達式的所有 PCRE 部分(前瞻和後視),您可能認為我們可以將此正則表達式與 plain 一起使用grep。不幸的是,我們不能;上面的命令取決於沒有的選項。-o*N*``grep

但是,我們可以將它與sed!

sed -n -r "s|.*<div\sclass='cls\s'>(.*)</div>.*|\1|p"

pcregrep命令一樣,它會搜尋整個正則表達式(包括 之前<div …>或之後的內容</div>,因為我.*在開頭和結尾添加了內容)並將其替換為 #1 擷取組(唯一的一個)。最後p的 導致它列印匹配的行;該-n選項導致它不列印不匹配的行。

以上|用作正則表達式分隔符,因為正則表達式包含/. 如果要/用作分隔符,則必須轉義文本/(in </div>):

sed -n -r "s **/** .*<div\sclass='cls\s'>(.*)< **\/** div>.* **/** \1 **/** p"

不幸的是,sed沒有遞歸搜尋功能。-r選項sed類似於; _ -E_ grep它指定了擴展正則表達式 (ERE) 的使用。沒有它,我們將需要使用\(and\)擷取組:

sed -n "s/.*<div\sclass='cls\s'> **\(** .* **\)** <\/div>.*/\1/p"

當然,您可以通過執行來進行遞歸sed搜尋find

PS 如果您在一行中有多個<div …>…對,這些命令將只列印第一個。</div>``sed 6. 您正在執行錯誤的遞歸(目錄樹)搜尋。

grep -r*正則表達式**.html

pcregrep同樣)查看每個.html文件,然後查看名稱以 . 結尾的任何目錄中及其下 的每個文件。因此,如果(不太可能?)您有一個名為 的子目錄,那麼上述命令將搜尋該目錄中的每個文件(即使它被稱為or )。如果(我認為更有可能)您有名稱類似於and的子目錄,則不會搜尋它們。 .htmlfoo.html``Makefile``README.txt``page42``index

你想做的是:

grep -r --include='*.html'*正則表達式*。

它對從**.**(目前目錄)開始的所有目錄進行遞歸搜尋,只查看名稱匹配的文件*.html

引用自:https://unix.stackexchange.com/questions/483681