encontra texto nos arquivos e copia para um csv

0

Eu preciso extrair o texto em um monte de arquivos html (cerca de 500K deles) O texto a ser copiado parece com <div class='cls '>text to be copied including some<span>and <p></p></span>and more text</div>

que resolvi (?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)

Li outras questões sobre como fazer isso com o grep e achei que o comando seria

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

E isso não funciona. O que estou fazendo errado?

também experimentou pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" --file-list=fl.txt > output.txt - não faz nada e pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" > output.txt - nada

EDIT 1: Tentei a sugestão abaixo nos seguintes formatos:

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

e algumas outras permutações, ainda nada

    
por flish 23.11.2018 / 15:04

3 respostas

2

Não sei por que você adicionou todos os assobios de anúncios de sinos. Este regex simples funcionou para mim:

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>
    
por 23.11.2018 / 15:28
1
grep -r "/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" *.html > output.txt

Está trabalhando recursivamente, mas não interpretando regex. Tente usar o fgrep em seu lugar ou grep -f -r. Além disso, você pode querer touch output.txt e usar > > em vez de >.

    
por 23.11.2018 / 15:21
1

Você tem seis problemas:

  1. Você está incluindo / no início e no final de sua regex. Você digita /regex/ em sed , vi , e outros programas para fazer uma pesquisa, mas você não precisa dela para grep . E, de fato, grep apenas incluirá caracteres literais / no padrão.
  2. Para usar os PCREs em (simples) grep , você deve usar -P .
  3. Não existe -regexp ; tem que ser --regexp . Ou deixe o —regexp= e apenas dê a expressão regular como um argumento sem adornos, como você faz em grep .

Depois de corrigir os erros acima, ambos os comandos ( grep -P e pcregrep ) tipo de trabalho - mas eles imprimiram a linha inteira contendo o padrão, incluindo qualquer texto antes do <div …> ou após o </div> .

  1. Para imprimir apenas o texto que correspondeu ao padrão, você deve especificar -o .

Mesmo depois de corrigir isso, recebi o <div …> na saída (mas não o texto antes do <div …> , ou o </div> ou qualquer coisa depois dele). Então,

  1. Há algo errado com o seu grupo de olhar para trás está sendo incluído no jogo.

    Infelizmente, eu não sei o suficiente sobre os PCREs para saber exatamente qual é o problema ou como corrigi-lo. Felizmente, eu sei o suficiente sobre pcregrep para conhecer uma solução alternativa. Se você tiver vários grupos de captura em sua regex, pcregrep permite escolher qual (is) você deseja gravar na saída. Então, podemos fazê-lo funcionar em pcregrep transformando o look-behind em um grupo de captura, e depois ignorá-lo:

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

    Mas mesmo isso é mais complicado do que precisa ser. O primeiro grupo ( <div …> ) não precisa ser um grupo de captura; isto é, não precisa ser um grupo. Da mesma forma, o último grupo (o grupo de look-ahead </div> ) não precisa ser um grupo. A única coisa que precisa ser um grupo é a parte que você quer capturar - a parte entre o <div …> e o </div> :

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

    Observe que eu mudei -o2 para -o1 porque agora há apenas um grupo.

    BTW, como RudiC descobriu (mas não mencionou), quase nenhuma dessas barras invertidas é necessária. AFAICT, os únicos que você precisa são aqueles nas sequências \s ; então podemos simplificar o acima para:

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

    Agora que eliminamos todas as partes PCRE do regex (olhar em frente e olhar para trás), você pode pensar que podemos usar essa regex com grep simples. Infelizmente não podemos; o comando acima depende da opção -oN , qual grep não tem.

    No entanto, podemos usá-lo com sed !

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

    Como o comando pcregrep , ele pesquisa o regex inteiro (incluindo material antes do <div …> ou depois do </div> , porque eu adicionei .* no começo e no fim) e o substitui pelo grupo de captura nº 1 (o único). O p no final faz com que ele imprima as linhas correspondentes; a opção -n faz com que não imprima linhas que não correspondem.

    O acima usa | como um delimitador regex porque o regex contém / . Se você quiser usar / como seu delimitador, então você tem que escapar do textual / (em </div> ):

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

    Infelizmente, sed não possui um recurso de pesquisa recursiva. A opção -r para sed é como a opção -E para grep ; especifica o uso de expressões regulares estendidas (EREs). Sem isso, precisaríamos usar \( e \) para o grupo de captura:

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

    É claro que você pode fazer uma pesquisa recursiva executando sed a find .

    P.S. Se você tiver vários pares <div …></div> em uma linha, esses comandos sed imprimirão apenas o primeiro.

  2. Você está fazendo a busca recursiva (árvore de diretórios) errada.

    grep -r regex *.html

    (e pcregrep o mesmo) procura em todos os arquivos .html , e, em seguida, analisa todos os arquivos em e sob qualquer Diretório cujo nome termina com .html . Então, no evento (improvável?) que você tem um subdiretório chamado foo.html , então o comando acima procuraria todos os arquivos nesse diretório (mesmo que seja chamado Makefile ou README.txt ). Se (como eu suponho que é mais provável) você tem subdiretórios com nomes como page42 e index , eles não seriam pesquisados.

    O que você quer fazer é:

    grep -r --include='*.html' regex .

    que faz uma pesquisa recursiva de todos os diretórios a partir de . (o diretório atual), olhando apenas para arquivos cujos nomes correspondem a *.html .

por 23.11.2018 / 15:59

Tags