다운로드한 웹페이지에서 문자열을 찾으려고 합니다 curl
. 나는 grep
일치하는 문자열을 찾는 데 사용합니다.정규식무늬.
아래는 내가 찾으려는 문자열입니다.
./download/file.php?id=86753
이 문자열은부분웹 페이지에 있는 더 큰 문자열은 다음과 같습니다.
href="./download/file.php?id=86753"
제가 사용하는 만트라 grep
는 다음과 같습니다.
grep -Eo '\.\/download\/file\.php\?id=[0-9]+' dlfile.html
그런데 발견됐어요아무것도 없다html 파일에서. 그러나 grep
다음과 같이 수정하면 2개의 일치 항목이 생성됩니다. 이것첫 번째 게임두 번째는 쓸모없는 방해물이므로 포함해서는 안 됩니다.
grep -Eo '\/download\/file\.php\?id=[0-9]+' dlfile.html
/download/file.php?id=86753
/download/file.php?id=62517
두 번째(원치 않는) 일치 항목이 포함된 문자열은 다음과 같습니다.
href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"
.
문제는 문자열의 선행(점)이 인식되지 않는 것 같습니다. 이것이 원하는 문자열과 원하지 않는 문자열의 주요 차이점입니다.
Q: 이것이 작동하지 않는 이유는 무엇이며 무엇이 필요합니까?
내 환경: Debian 파생 버전(Raspberry Pi), "bullseye" 버전
나는 어느 것을 사용하고 있습니까 grep
?bash
$ grep --version
grep (GNU grep) 3.6
...
$ bash --version
GNU bash, version 5.1.4(1)-release (arm-unknown-linux-gnueabihf)
답변1
grep -E
ERE(확장 정규 표현식)가 필요합니다 . 점은 항상 리터럴로 이스케이프되어야 합니다. 물음표는 ERE에 유효한 연산자이므로 리터럴과 일치시키려면 이스케이프해야 합니다.
echo 'href="./download/file.php?id=86753"' |
grep -Eo '\./download/file.php\?id=[0-9]+'
물어,
grep이 선행 "."을 무시하는 이유는 무엇입니까?
문제는 문자열의 선행 .(점)을 인식하지 못하는 것 같습니다.
귀하의 패턴은 일치하며 리터럴 포인트가 필요합니다(이것이 바로 그 \.
의미입니다). 그러나 질문에 설명하신 문자열은 검색하려는 웹페이지에 나타나지 않습니다. grep
이를 무시하지 마십시오. 바라보다:
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//a[@class="postlink"]/@href' -n
https://forums.raspberrypi.com/download/file.php?id=86753
https://web.archive.org/web/20190824162104/https://www.raspberrypi.org/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32
나는 당신이 이들 중 첫 번째를 원한다고 가정하고 있으므로 그것을 추출해 보겠습니다.
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n
https://forums.raspberrypi.com/download/file.php?id=86753
다음으로 시작하는 /download
부분 만 원하는 경우
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n |
sed -E 's!^https?://[^/]+!!'
/download/file.php?id=86753
grep
작업에 적합한 도구 대신 실제로 사용하려는 경우 동일한 결과가 반환됩니다.
grep -Po 'https?://[^/]+\K/download/file.php\?id=\d+' BDegguyM
/download/file.php?id=86753
답변2
제목 줄의 질문에 대한 답변:
grep이 선행 "."을 무시하는 이유는 무엇입니까?
간단히 말해서, 사실이 아닙니다.
1개의 파일에 함께 제공한 2개의 샘플 입력 줄을 사용합니다.
$ cat dlfile.html
href="./download/file.php?id=86753"
href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"
s 앞에 있는 원치 않는(아마도 무해하지만 POSIX에 따라 정의되지 않은 동작에 확실히 의존함) 백슬래시를 제거하고 질문에서 /
2개의 명령을 실행합니다.grep
$ grep -Eo '\./download/file\.php\?id=[0-9]+' dlfile.html
./download/file.php?id=86753
$ grep -Eo '/download/file\.php\?id=[0-9]+' dlfile.html
/download/file.php?id=86753
/download/file.php?id=62517
첫 번째는 grep
선행을 포함하고 .
선행이 있는 입력의 문자열과만 일치하는 .
반면, 두 번째는 grep
선행을 포함하지 않고 .
당연히 a로 시작하지 않는 입력의 2개 문자열과 일치합니다 .
.
grep
위의 첫 번째 사항에 대한 귀하의 의견과 관련하여 :
그러나 이것은 html 파일에서 아무것도 찾지 못합니다.
그 다음에:
- 질문의 grep 명령이 실제로 사용하는 명령과 다릅니다.
- 실제 HTML 파일에는 샘플 입력으로 사용하기 위해 제공한 문자열이 포함되어 있지 않습니다.
따라서 명령이 어떤 모양인지 또는 입력이 어떤 모양인지 모르는 경우 일부 입력을 구문 분석하는 명령을 디버깅하는 데 도움을 주기 위해 실제로 할 수 있는 일은 없습니다.
답변3
여기에는 이미 많은 댓글이 달렸습니다. 그들 중 일부는 정당한 우려와 질문을 제기했습니다. 마침내 문제가 해결되었다고 생각하며 마무리를 위해 여기에 게시합니다.
여러분이 수집한 대로, 나는 필요한 정보 항목이 포함된 문자열의 URL을 "스크래핑"하고 있습니다. 약 2년 전에 저는 이 작업을 "자동화"하는 스크립트를 개발했는데 완벽하게 작동했습니다. 이 스크립트는 주로 다음 두 가지 작업을 수행합니다.
curl
&grep
웹 페이지- 결과에 따라 다른
grep
조치를 취하십시오.
"뭔가 달라졌어"며칠 전. 내 "신뢰할 수 있는" 스크립트는 실행될 때마다 오류가 발생하기 시작했습니다. 이 오류는 grep
문자열을 찾을 수 없다는 것을 나타냅니다. 내가 grep
사용하는 것 :
curl blah-blah | grep -o '\.\/download\/file\.php?id.[0-9]*'
오늘날까지도 나는 아무것도 변한 것이 없다는 것을 모릅니다. 변경 사항 중 하나는 사이트가 "CloudFlare"라는 회사에 아웃소싱되었다는 것입니다. 다른 하나는 더 이상 curl
브라우저 다운로드를 처리하는 것과 동일한 방식으로 다운로드를 처리 하지 않는 것 같습니다 . 또 다른 변화가 일어나고 있는 것 같습니다.
내 질문에 반영된 혼란은 부분적으로 이러한 사이트의 변경으로 인한 것입니다.하지만 그건 대부분 나 때문이야. 질문을 게시하기 전에 좀 더 인내심을 갖고 오류를 더 철저하게 조사했어야 했습니다. 관련된 모든 분들께 사과드립니다.
제가 이 경험을 통해 배웠다고 주장하는 한 가지는 다음과 같습니다.grep
HTML을 구문 분석하는 데 적합한 도구가 아닙니다.. 공유할 참고 자료가 두 개 있습니다.
이것논란이 많은철사SO에서 HTML을 구문 분석하기 위해 정규식 재사용
이것Hiks Gerganov의 정보 게시물제목은 "셸의 HTML 태그 사이에서 텍스트를 추출하기 위한 HTML 구문 분석"입니다.
답변4
\/
일반으로 변경하면 정상적으로 작동합니다 /
.
#!/usr/bin/sh
printf 'href="%s"\n' \
'./download/file.php?id=86753' \
'elsewhere/download/file.php?id=86753' |
grep -oE '\./download/file\.php\?id=[0-9]+'
산출:
./download/file.php?id=86753
원치 않는 아슬아슬한 상황을 더 잘 거부하기 위해 \B
시작과 끝 부분에 추가하는 것을 고려할 수도 있습니다 .\b