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>
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
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>
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 >.
Você tem seis problemas:
/
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. grep
, você deve usar -P
. -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>
.
-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,
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.
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
.