mac-hosts
MAC 주소와 관련 호스트 이름이 포함된 파일이 있습니다.
e4:5f:01:21:79:01 PF3
e4:5f:01:21:79:03 PF3-BR0
e4:5f:01:21:79:be PF2
e4:5f:01:21:79:c0 PF2-BR0
올바른 형식의 MAC 주소와 호스트 이름이 있는 행 수를 계산하려면 다음 표현식을 사용합니다.
FILTERED=$(cat mac-hosts | grep -P -c '/^[a-f0-9]{2}([:-])([a-f0-9]{2}\1){4}[a-f0-9]{2} [a-z0-9]*([-][a-z0-9]*)?$/i')
이 표현의 모든 버전에서 나는 FILTERED = 0
결과를 얻습니다.
확인했습니다https://regex101.com/파일의 모든 행은 mac-hosts
역참조가 의미가 없는 GoLang 및 Rust를 제외하고 제공된 모든 버전에서 오류나 경고 없이 필터 표현식과 올바르게 일치합니다. 이 man
페이지 도 조사했지만 grep
필터가 작동하지 않는 이유를 찾을 수 없습니다.
-P
그렇지 않다면 grep: Invalid back reference
Perl 호환 정규식 구문을 사용하고 있다는 것을 알고 있습니다.
저는 이 결함이 최신 버전의 Linux를 실행하는 Raspberry Pi 4B에서 발생했다는 것을 처음 발견했습니다.
pi@PF2:~ $ uname -a
Linux PF2 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux
pi@PF2:~ $ grep -V
grep (GNU grep) 3.6
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Mike Haertel and others; see
<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
git-bash
이후 Windows 10에서 실행할 때 동일한 동작이 관찰되었습니다.
이 문제를 어떻게 디버깅하고 예상 결과를 얻을 수 있습니까 FILTERED = 4
? 결과는 어디에 있습니까?
고쳐 쓰다
i
답장을 보내 주셔서 감사합니다. 답을 봤을 때 분명했습니다. 문자열의 일부와 일치하지 않는 슬래시를 분리해야 하는 상황과 "대소문자 무시" 플래그를 생각하고 있었습니다 . 명령줄의 경우 grep
구분 기호가 사용되지 않으며 "대소문자 무시"는 스위치로 설정됩니다 -i
.
FILTERED=$(grep -Pic '^[a-f0-9]{2}([:-])([a-f0-9]{2}\1){4}[a-f0-9]{2} [a-z0-9]*([-][a-z0-9]*)?$' mac-hosts)
업데이트 2
호스트 이름에 여전히 문제가 있습니다.아니요두 번째 부분(하이픈 및 기타 alm)이 있습니다. 이 이름 끝에는 (놀랍지도 않게) 화면에 표시되지 않는 공백이 있는 것으로 나타났습니다. 후행 공백을 찾기 위해 일치 문자열에 다른 구성 요소를 추가했습니다. 이제 최종 테스트가 제대로 작동합니다.
FILTERED=$(grep -Pic '^[a-f0-9]{2}([:-])([a-f0-9]{2}\1){4}[a-f0-9]{2} [a-z0-9]*([-][a-z0-9]*)?[[:space:]]$' mac-hosts)
작성자가 줄 끝에서 테스트를 제거한 제안된 편집 내용을 롤백했습니다. 그러나 허용되는 잘못된 줄은 필터링되지 않습니다. 예를 들어 호스트 이름 뒤의 구두점은 이 형식에서 허용되지 않습니다.
답변1
grep이 파일의 행과 일치하지 않는 이유는 언뜻 보기에 정규식에 파일의 행에 나타나지 않는 선행 슬래시( /
) 문자와 후행 문자( )가 있으므로 /i
일치하는 라인. Perl 스크립트에서 /
정규식의 시작과 끝(및 후행 슬래시 뒤의 수정자)은 정규식 자체의 일부가 아니라 정규식과 관련된 구분 기호 및 수정자입니다.
나는 두 가지를 제안합니다:
- POSIX 문자 클래스를 사용하여 MAC 주소 및 호스트 이름과 일치하는 더 간단한 표현식을 만듭니다.
grep
-c 옵션 없이 명령줄에서 명령을 테스트하고 정규식이 올바른 줄과 일치할 때까지 터미널 창에 출력을 보냅니다. 정확하다면 -c를 추가하고 개수를 확인하세요. 테스트가 성공한 후에만 스크립트의 변수에 출력을 캡처합니다.
이 명령은 Ubuntu 20.04 시스템에 설치된 GNU grep을 사용하여 작동합니다.
grep -E '^[[:xdigit:]:]+ +[[:alnum:]_-]+' mac-hosts
파일을 호출하거나 로 파이핑 grep
하지 않고도 파일에서 직접 읽을 수 있습니다 .cat
grep
이 확장 정규식(-E 옵션으로 활성화)은 공백 문자로 구분된 인쇄 가능한 문자의 두 "필드"와 일치합니다. 첫 번째 필드는 줄의 시작 부분에 있으며 하나 이상의 16진수 문자 또는 콜론( :
) 문자로 구성됩니다. 두 번째 필드는 하나 이상의 영숫자, 밑줄( _
) 또는 대시( -
) 문자로 구성됩니다.
이는 첫 번째 필드에 콜론으로 구분된 2개의 16진수 문자로 구성된 정확히 6개의 필드가 있도록 강제하지 않으며 두 번째 필드에 영숫자 문자(또는 대문자만) 없이 대시나 밑줄만 표시하도록 강제하지 않습니다. 새로운 사용 사례에 맞게 이해하고 맞춤설정하기가 훨씬 쉽습니다.
위의 방법을 사용하여 크게 잘못된 파일 행(예: 호스트 이름 누락)을 필터링한 다음 "양호한" 행의 필드에 대해 더 엄격한 구문 검사를 수행하는 서브루틴을 작성합니다. 당신이 신경 쓴다면, 그렇습니다. 내 스크립트에서는 추가 구문 검사 서브루틴을 작성하지 않고도 위의 내용만으로 작업을 완료할 수 있습니다.
일치해야 하는 줄과 일치하도록 정규식을 조정한 후 -c 옵션을 추가하여 줄 자체가 아닌 일치하는 줄의 개수를 출력할 수 있습니다. -E regex 옵션을 명령줄의 표현식과 함께 사용하는 것 grep -c -E
보다 옵션과 인수의 순서를 지정하는 것이 좋습니다 . grep -E -c
기술적으로는 불필요하지만 이와 같은 작은 것들은 스크립트를 읽는 사람이 스크립트를 이해/업데이트하는 데 도움이 될 수 있습니다. (보통 몇 달 후입니다.)
Perl 표현식을 선호한다면 -E 대신 -P를 사용하여 명령을 수행하면 됩니다.