여러 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
그리고 다른 순열은 아직 없습니다
답변1
왜 이렇게 멋진 광고 종소리와 휘파람을 추가했는지 잘 모르겠습니다. 이 간단한 정규식은 나에게 효과적입니다.
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>
답변2
다음과 같은 6가지 질문이 있습니다.
/
정규식의 시작과 끝 부분에 콘텐츠를 포함합니다 . 검색할 다른 프로그램을 입력하지만 필요하지 않습니다. 실제로 패턴에는 리터럴 문자만 포함됩니다./regex/
sed
vi
grep
grep
/
- (일반)에서 PCRE를 사용하려면
grep
를 사용해야 합니다-P
. - 그런 일은 없을
-regexp
것입니다--regexp
. 또는 에서와 같이 이를 생략하고—regexp=
정규식을 순진한 인수로 제공합니다grep
.
위의 오류를 수정한 후에는 ( grep -P
및 ) 명령이 모두 작동했지만 앞이나 뒤의 텍스트를 pcregrep
포함하여 패턴이 포함된 전체 줄을 인쇄했습니다 .<div …>
</div>
- 패턴과 일치하는 텍스트만 인쇄하려면 를 지정해야 합니다
-o
.
문제를 해결했지만 여전히 <div …>
출력에 해당 내용이 표시됩니다(그러나 이전 텍스트 <div …>
나 </div>
이후의 텍스트는 표시되지 않음). 그래서,
후방 보기 그룹에 문제가 있습니다. 경쟁에 포함되어 있습니다.
안타깝게도 저는 문제가 무엇인지, 해결 방법을 정확히 알 수 있을 만큼 PCRE에 대해 충분히 알지 못합니다. 다행히도 나는
pcregrep
해결책을 충분히 알고 있습니다. 정규식에 캡처링 그룹이 여러 개 있는 경우pcregrep
출력을 쓸 캡처링 그룹을 선택할 수 있습니다. 따라서pcregrep
LookBehind를 캡처 그룹으로 변환한 다음 이를 무시하여 작동하게 할 수 있습니다.pcregrep -o2-r "(\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)"
그러나 이것조차도 필요한 것보다 더 복잡합니다. 첫 번째(
<div …>
) 그룹은 캡처 그룹일 필요는 없습니다. 즉, 그룹일 필요는 없습니다. 마찬가지로 마지막 그룹(</div>
예측 그룹)은 그룹일 필요가 전혀 없습니다. 그룹이 되어야 하는 유일한 것은 캡처하려는 부분<div …>
과 다음 사이의 부분 입니다</div>
.pcregrep-o1-r "\<div\sclass\=\'cls\s\'\>(.*)\<\/div\>"
이제 세트가 하나만 있기 때문에
-o2
으로 변경했습니다 .-o1
그런데 다음과 같이루딕이 발견했습니다(그러나 언급되지는 않음) 이러한 백슬래시는 거의 필요하지 않습니다. AFAICT, 필요한 것은
\s
문자열에 있는 것뿐이므로 위의 내용을 다음과 같이 단순화할 수 있습니다.pcregrep -o1 -r "<div\sclass='cls\s'>(.*)</div>"
이제 정규식의 모든 PCRE 부분(앞으로 및 뒤로)을 제거했으므로 이 정규식을 일반 정규식과 비교할 수 있다고 생각할 수 있습니다
grep
. 불행하게도 위 명령은 옵션에 따라 다릅니다. 아니요.-oN
grep
그러나 !와 결합할 수 있습니다
sed
.sed -n -r "s|.*<div\sclass='cls\s'>(.*)</div>.*|\1|p"
해당
pcregrep
명령과 마찬가지로 이 명령은 전체 정규식( 처음과 끝에 항목을 추가 했기 때문에<div …>
이전 또는 이후에 오는 항목 포함 )을 검색하고 이를 #1 캡처 그룹(유일한 항목)으로 바꿉니다. 마지막 옵션은 일치하는 행을 인쇄하게 하며, 이 옵션은 일치하지 않는 행을 인쇄하지 않도록 합니다.</div>
.*
p
-n
위의
|
정규식에는 가 포함되어 있으므로 정규식 구분 기호로 작동합니다/
. 이를 구분 기호로 사용하려면/
텍스트를 이스케이프해야 합니다/
(</div>
).sed -n -r "s/.*<div\sclass='cls\s'>(.*)<\/파티션>.*/\1/"
불행히도
sed
재귀 검색 기능은 없습니다. 이 옵션은-r
ERE(확장 정규 표현식) 사용을 지정하는 것과 유사합니다 . 이것이 없으면 및 캡처 그룹을 사용해야 합니다.sed
-E
grep
\(
\)
sed -n "s/.*<div\sclass='cls\s'>\(.*\)<\/div>.*/\1/p"
sed
물론 를 실행하여 재귀 검색을 수행할 수 있습니다find
.PS 한 줄에 ... 쌍이 여러 개인 경우
<div …>
이 명령은 첫 번째 쌍만 인쇄합니다.</div>
sed
재귀(디렉토리 트리) 검색이 잘못되었습니다.
grep -r정규식*.html
(
pcregrep
다시) 각 파일을 살펴.html
보고모든어떤 파일이든 이름이 다음으로 끝나는 디렉토리.html
. 따라서 (아마도?) 라는 하위 디렉터리가 있는 경우foo.html
위 명령은 검색을 수행합니다.모든Makefile
해당 디렉토리에 있는 파일입니다( 또는 라고 불리는 경우에도 마찬가지입니다README.txt
). (내 생각에는)page42
및 와 유사한 이름을 가진 하위 디렉터리가 있는 경우index
해당 디렉터리는 검색되지 않습니다.당신이하고 싶은 일은 :
grep -r --include='*.html'정규식.
다음에서 시작하는 모든 디렉토리에 대해 재귀 검색을 수행합니다.
.
(현재 디렉터리) 이름이 일치하는 파일만 봅니다*.html
.
답변3
grep -r "/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" *.html > output.txt
재귀적으로 작동하지만 정규식을 해석하지 않습니다. 대신 fgrep 또는 grep -f -r을 사용해 보십시오. 또한 touch output.txt
> 대신 >>를 사용할 수도 있습니다.