런타임에 제공된 숫자를 기반으로 여러 패턴을 일치시키기 위해 grep 및 명령을 구성하는 방법은 무엇입니까?

런타임에 제공된 숫자를 기반으로 여러 패턴을 일치시키기 위해 grep 및 명령을 구성하는 방법은 무엇입니까?

좀 수출했는데마이크로 소프트 워드문서를 일반 텍스트로 변환하고 이 함수를 사용하여 .txt현재 디렉터리에 있는 파일의 내용을 구문 분석합니다.

mo1 () {
for i in *.txt; do
    echo "File: $i"
    grep -n -HC 1 "$@" "$i"
done
}

찾아야 할 패턴이 두 개 이상인 경우 그렇게 할 수 있습니다 mo1 | grep pattern2. 하지만 grep -E 'pattern1.*pattern2[.*...]...'런타임 시 함수에 제공되는 패턴 수(예: 등) 에 따라 결과가 달라지는 작업을 수행하려면 mo1 pattern1 pattern2 [...]어떻게 해야 할까요? 배열이 항목 수를 제공할 수 있다는 것을 알 수 있으며 @루프(finalpattern='$1.*$2.*$3')를 통해 변수를 구성할 수 있으며 이는 결국 에 사용되는 표현식이 됩니다 grep. 그런데 함수에서 표현식을 만드는 부분을 추상화하는 방법을 알 수 없나요? 아니면 이와 같은 작업을 수행하는 더 좋고 쉬운 방법이 있습니까?

답변1

printf내장된 기능을 활용할 수 있습니다 .

mo1 () {
  for file in *.txt; do
    grep -n -C1 "$(printf "%s.*" "$@")" "$file"
  done
}

이 간단한 버전은 .*마지막 요소 뒤에 삽입됩니다. 이 특정 사용 사례에서는 중요하지 않지만 다른 경우(예 grep -o: ..*

mo1 () {
  pattern=$(printf "%s.*" "$@")
  pattern=${pattern%??}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

Bash에서는 printf출력을 변수에 직접 넣을 수 있는데, 이는 명령 대체를 사용하는 것보다 약간 빠릅니다(그러나 이는 하위 쉘이 느린 Cygwin에서도 문제가 되지 않습니다).

mo1 () {
  printf -v pattern "%s.*" "$@"
  pattern=${pattern%??}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

위치 매개변수 사이에 단일 문자를 삽입하려면 IFS해당 문자를 설정하고 를 사용 하면 됩니다 "$@". 하지만 이 방법은 구분 기호가 두 문자 이상인 경우에는 작동하지 않습니다. ksh, bash에서는 패턴에 나타나지 않는 문자가 있을 경우 이를 이용하여 조인한 후 교체를 수행할 수 있습니다. 예를 들어, 여기서는 패턴에 개행 문자가 포함되는 것이 의미가 없습니다.

mo1 () {
  typeset IFS=$'\n'
  typeset pattern="$*"
  pattern=${pattern//$'\n'/.*}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

zsh에는 물론 직접적인 방법이 있습니다.

mo1 () {
  for file in *.txt; do
    grep -n -C1 ${(j:.*:)@} $file
  done
}

답변2

또는 --filegrep 옵션을 사용할 수 있습니다.

-f FILE, --file=FILE
    Obtain patterns from FILE, one per line.  The empty file contains
    zero patterns, and therefore matches nothing.  (-f is specified by POSIX.)

관련 정보