grep에 대한 여러 -e 옵션

grep에 대한 여러 -e 옵션

여러 모드를 전달하고 싶고 각 모드에 옵션을 적용하는 방법에 대한 grep많은 솔루션이 있습니다 .-e

다양한 모드가 배열에 저장됩니다 ptrn. 배열 요소의 공백은 -e패턴에 개별적으로 전달되지 않기 때문에 잘못 해석될 수 있는지 궁금합니다 .

가능성은

가능성 1

mptrn=$( printf -- ' -e %s' "${ptrn[@]}" )
grep -E "$mptrn" -- "$flnm"

가능성 2

for i in "${!ptrn[@]}"; do
  ptrn[$i]="-e ${ptrn[$i]}"
done
grep -E "${ptrn[@]}" -- "$flnm"

가능성 3

eptrn=()
for i in "${!ptrn[@]}"; do
  eptrn+=("-e" "${ptrn[$i]}")
done
grep -E "${eptrn[@]}" -- "$flnm"

어떤 솔루션에서든 발생할 수 있는 문제는 무엇입니까?

답변1

이렇게 놔두세요 ptrn=(" a b" " 333 22 1 ").

답변 1:

mptrn=$( printf -- ' -e %s' "${ptrn[@]}" )
grep -E "$mptrn" -- "$flnm"

명령의 전체 출력은 에 할당되며 mptrn, 배열의 요소에 공백 문자가 포함되어 있으면 사용된 형식으로 인해 해당 요소를 구별할 수 없습니다. (선행 및 후행 공백 문자 포함)이 mptrn포함됩니다 . -e a b -e 333 22 1실행될 때 grep인용된 인수는 선행 공백으로 인해 패턴 인수로 해석되며, 이는 "$mptrn"달성하려는 것이 아닌 지정된 파일에서 항목을 검색합니다. 이 작업과 같은 작업을 수행하려면 다음을 사용할 수 있습니다.IFS범위.

[ "${IFS+x}" = x ] && OLD_IFS=$IFS
IFS=$(printf '\x7f')
mptrn=$(printf "-e${IFS}%s${IFS}" "${ptrn[@]}")
# note that we don't use quotes
grep -E $mptrn -- "$flnm"
if [ "${OLD_IFS+x}" = x ]; then IFS=$OLD_IFS; else unset IFS; fi

답변 2:

for i in "${!ptrn[@]}"; do
  ptrn[$i]="-e ${ptrn[$i]}"
done
grep -E "${ptrn[@]}" -- "$flnm"

이 답변은 검색된 패턴에 선행 공백이 포함된다는 점을 제외하면 원하는 결과에 가깝습니다. 즉, 생성된 명령은 다음과 같습니다.

grep -E "-e  a b" "-e  333 22 1 " -- file

공백을 제거하면 문제가 해결됩니다 ptrn[$i]=-e${ptrn[$i]}.


답변 3:

eptrn=()
for i in "${!ptrn[@]}"; do
  eptrn+=("-e" "${ptrn[$i]}")
done
grep -E "${eptrn[@]}" -- "$flnm"

이 대답은 정확합니다. 생성된 grep명령은 다음과 같습니다.

grep -E -e " a b" -e " 333 22 1 " -- file

답변2

이를 정규식으로 결합합니다. 예를 들어 임의의 패턴과 일치시키려는 경우 정규식 대체 연산자를 |OR로 사용할 수 있습니다.

먼저 join_bybash에서 함수를 만듭니다.

join_by () { 
    local d="$1";
    shift;
    printf '%s' "$1";
    shift;
    printf '%s' "${@/#/$d}"
}

perl이것은 내장 함수의 매우 간단한 복제입니다 join. 첫 번째 매개변수를 구분 기호로 사용한 다음 해당 구분 기호를 사용하여 추가적인 귀찮은 선행 또는 후행 구분 기호 없이 나머지 모든 매개 변수를 연결합니다.

그런 다음 다음과 같이 사용하십시오.

$ p=(a b c d e)
$ re=$(join_by '|' "${p[@]}")
$ echo $re
a|b|c|d|e

$re를 사용할 수 있습니다 grep -E(교체하려면 확장 정규식 "ERE"가 필요함).

grep -E "$re" filename

더 복잡한 부울 연산(예 a && b && ! (c || d || e: )을 수행해야 하는 경우 perl 또는 awk를 사용하세요. bash는 데이터 처리 언어로는 적합하지 않습니다.

관련 정보