awk 정규 표현식에서 연산과 대소문자를 구분하지 않습니까?

awk 정규 표현식에서 연산과 대소문자를 구분하지 않습니까?

두 개의 텍스트 패턴이 포함된 파일 이름을 일치시키려고 하는데 일치 프로세스에서 대소문자를 무시해야 합니다. 다음 정규 표현식은 작동하지 않습니다.

모든 정규식 및 문자열 작업에서 대/소문자를 무시하도록 awk 변수 'IGNORECASE'를 0이 아닌 값(에서 제안한 대로 info awk)으로 설정한 다음 두 개의 정규식을 사용하여 모든 파일을 인쇄하는 논리적 "and" 작업을 구축합니다.

$ ls -R | awk 'IGNORECASE = 1;/bingo/ && /number/;'


텍스트 패턴 "bingo" 및 "number"를 일치시키기 위해 미리보기(두 번째 미리보기가 필요하지 않다는 것을 알고 있음)를 사용하기 전에 데이터를 소문자로 변환해 보았습니다. 그러나 awk는 기본적으로 출력해야 하는 출력을 인쇄하지 않습니다.1,2

$ ls -R | awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

awk 또는 regex 구문의 어떤 부분이 잘못되었거나 누락되었으며, 추가 패턴이 같은 줄에 나타나는 경우에만 성공하는 대소문자 독립적 검색을 수행하는 올바른 방법은 무엇입니까?

고쳐 쓰다:

달리기에서

$ ls -R | awk '/bingo/'

파일 이름에 일치하는 문자열 상수 "bingo"가 포함되어 있지 않기 awk때문에 출력의 각 파일에 있는 줄에서 일치가 수행되는 것처럼 보입니다 . 이 경우 파이프에서 출력을 받을 때(즉, 파이프를 통해 전송)와 동일한 동작을 어떻게 얻을 수 있습니까?ls -Rawkawkgrep

답변1

첫 번째 스크립트를 작성하세요.

awk 'IGNORECASE = 1;/bingo/ && /number/;'
  1. 의견에서 지적했듯이 IGNORECASE는 dorks로 제한되며
  2. 귀하의 awk 코드는 다음과 같습니다:

    awk '(IGNORECASE = 1){print}; (/bingo/ && /number/){print}'
    

따라서 GNU awk에서는 대소문자를 구분하지 않고 일치를 수행하지만 다른 awk에서는 그렇지 않습니다. 그리고 항상 현재 줄을 인쇄합니다(할당이 참 조건 IGNORECASE=1으로 평가되기 때문에 1). 그런 다음 빙고와 번호를 포함하는 모든 줄을 인쇄합니다. 두번째.

두 번째 스크립트를 작성하세요.

awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

그것은 ?=PCRE 둘러보기입니다. awk는 PCRE가 아닌 ERE를 지원하므로 ERE에서 실제로 무엇을 의미하는지 고려해야 하지만 그것이 무엇이든 원하는 의미는 아닙니다.

귀하의 진술은 다음과 같습니다:

awk는 ls -R 출력에서 ​​각 파일의 행에 대해 일치를 수행하는 것으로 보입니다.

왜 그렇게 생각하는지 모르겠지만, 그렇지 않습니다.

나는 이것이 GNU awk에서 원하는 것이라고 생각합니다:

awk 'BEGIN{IGNORECASE=1}; /bingo/ && /number/'

또는:

awk -v IGNORECASE=1 '/bingo/ && /number/'

어떤 경우든:

awk '{lc=tolower($0)}; (lc ~ /bingo/) && (lc ~ /number/)'

답변2

현재 디렉토리나 문자열이 포함된 디렉토리에서 이름을 찾으려면 bingo어떤 경우에도 numberthrough의 출력을 전달하지 말고 다음을 사용하십시오.ls -Rawkfind

find . -iname '*bingo*' -iname '*number*'

-iname조건자는 비표준이지만 일반적으로 구현되며 주어진 와일드카드 패턴에 대해 현재 확인 중인 파일 이름과 대소문자를 구분하지 않고 일치합니다.

파일명을 알고 싶다면오직, 찾은 파일의 전체 경로 이름 대신 다음을 사용하십시오.

find . -iname '*bingo*' -iname '*number*' -exec basename {} \;

GNU를 사용하면 find다음을 사용할 수 있습니다.

find . -iname '*bingo*' -iname '*number*' -printf '%f\n'

를 사용하는 것보다 더 빠릅니다 basename.

두 단어의 순서가 " bingo뒤에 number" 라는 것을 알고 있는 경우 두 테스트 대신 -iname '*bingo*number*'with를 사용하세요.find-iname

찾고 있는 단어의 순서가 이것이라는 것을 알고 있다면 bash다음을 사용할 수도 있습니다.

shopt -s globstar      # enable ** to match across / in pathnames
shopt -s nocaseglob    # enable case-insensitive globbing
shopt -s failglob      # error when a pattern does not match anything

printf '%s\n' **/*bingo*number*

경로 이름의 파일 이름 부분을 얻으려면:

shopt -s globstar nocaseglob failglob

for name in **/*bingo*number*; do
    basename -- "$name"
done

또는 GNU가 있고 basename일치하고 싶지 않은 경우수천파일 수,

shopt -s globstar nocaseglob failglob

basename -a -- **/*bingo*number*

여기서 -a각 인수(여러 인수)의 파일 이름 부분을 표시하도록 유틸리티에 지시합니다.

Stéphane은 주석에서 두 하위 문자열의 순서를 무시하려면 bash확장된 globbing 패턴을 사용할 수 있다고 지적했습니다.

!(!(*bingo*)|!(*number*))

이는 다음을 제외한 모든 이름을 일치시켜 수행됩니다.원하지 않는다두 문자열 중 하나를 포함합니다. 그래서 당신은 얻을 것이다

shopt -s globstar nocaseglob failglob
shopt -s extglob  # for extended globbing patterns in bash

for name in **/!(!(*bingo*)|!(*number*)); do
    basename -- "$name"
done

관련된:

관련 정보