grep이 선행 "."을 무시하는 이유는 무엇입니까?

grep이 선행 "."을 무시하는 이유는 무엇입니까?

다운로드한 웹페이지에서 문자열을 찾으려고 합니다 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 -EERE(확장 정규 표현식)가 필요합니다 . 점은 항상 리터럴로 이스케이프되어야 합니다. 물음표는 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 파일에서 아무것도 찾지 못합니다.

그 다음에:

  1. 질문의 grep 명령이 실제로 사용하는 명령과 다릅니다.
  2. 실제 HTML 파일에는 샘플 입력으로 사용하기 위해 제공한 문자열이 포함되어 있지 않습니다.

따라서 명령이 어떤 모양인지 또는 입력이 어떤 모양인지 모르는 경우 일부 입력을 구문 분석하는 명령을 디버깅하는 데 도움을 주기 위해 실제로 할 수 있는 일은 없습니다.

답변3

여기에는 이미 많은 댓글이 달렸습니다. 그들 중 일부는 정당한 우려와 질문을 제기했습니다. 마침내 문제가 해결되었다고 생각하며 마무리를 위해 여기에 게시합니다.

여러분이 수집한 대로, 나는 필요한 정보 항목이 포함된 문자열의 URL을 "스크래핑"하고 있습니다. 약 2년 전에 저는 이 작업을 "자동화"하는 스크립트를 개발했는데 완벽하게 작동했습니다. 이 스크립트는 주로 다음 두 가지 작업을 수행합니다.

  1. curl& grep웹 페이지
  2. 결과에 따라 다른 grep조치를 취하십시오.

"뭔가 달라졌어"며칠 전. 내 "신뢰할 수 있는" 스크립트는 실행될 때마다 오류가 발생하기 시작했습니다. 이 오류는 grep문자열을 찾을 수 없다는 것을 나타냅니다. 내가 grep사용하는 것 :

curl blah-blah | grep -o '\.\/download\/file\.php?id.[0-9]*'

오늘날까지도 나는 아무것도 변한 것이 없다는 것을 모릅니다. 변경 사항 중 하나는 사이트가 "CloudFlare"라는 회사에 아웃소싱되었다는 것입니다. 다른 하나는 더 이상 curl브라우저 다운로드를 처리하는 것과 동일한 방식으로 다운로드를 처리 하지 않는 것 같습니다 . 또 다른 변화가 일어나고 있는 것 같습니다.

내 질문에 반영된 혼란은 부분적으로 이러한 사이트의 변경으로 인한 것입니다.하지만 그건 대부분 나 때문이야. 질문을 게시하기 전에 좀 더 인내심을 갖고 오류를 더 철저하게 조사했어야 했습니다. 관련된 모든 분들께 사과드립니다.

제가 이 경험을 통해 배웠다고 주장하는 한 가지는 다음과 같습니다.grepHTML을 구문 분석하는 데 적합한 도구가 아닙니다.. 공유할 참고 자료가 두 개 있습니다.

  1. 이것논란이 많은철사SO에서 HTML을 구문 분석하기 위해 정규식 재사용

  2. 이것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

관련 정보