POSIX 쉘에서 알 수 없는 개수의 인수를 사용하여 명령을 실행하는 방법은 무엇입니까?

POSIX 쉘에서 알 수 없는 개수의 인수를 사용하여 명령을 실행하는 방법은 무엇입니까?

현재 디렉토리에서 여러 단어를 검색하고 싶습니다. 이를 달성하기 위해 나는 이와 같은 것을 사용합니다.

grep -e "word1" -e "word2" -R .

이것은 훌륭하게 작동합니다.

grep한 단계 더 나아가 개행 문자의 모든 단어를 포함하는 사전 파일을 생성하고 해당 사전을 사용하여 명령을 생성하고 싶었습니다 .

예를 들어 다음 사전 파일이 있습니다.

one
two
three
more

이 명령을 만들고 싶습니다.

grep -e "one" -e "two" -e "three" -e "more" -R .

나는 이것이 bash다음과 같은 배열로 이루어질 수 있다는 것을 알고 있습니다.

pattern=()
while IFS= read -r line; do
    pattern+=("-e" "$line")
done < "$dictionary"

grep "${pattern[@]}" -R .

하지만 POSIX 전용 셸을 사용하여 이를 수행하는 방법은 무엇입니까?

grep문자열을 명령으로 생성하고 를 사용하여 실행할 수 있다는 것을 알고 있지만 eval사전 파일은 무엇이든 될 수 있으므로 이것이 안전하지 않은 것 같습니다.

  • 어떤 해결책이 있습니까 eval?
  • "안전한" 해결책이 있나요 eval?

답변1

grep제공된 -f또는 -F스위치를 사용하고 싶지 않으십니까 grep? grep매뉴얼 페이지 에서 :

   -F, --fixed-strings
        Interpret PATTERN as a list of fixed strings, separated by 
        newlines, any of which is to be matched.  (-F is specified by 
        POSIX.)

   -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.)

$ grep -F somefile.txt -R .

답변2

POSIX 쉘에는 배열이 있습니다: 위치 매개변수( $1, $2, ...), 집합적으로 로 액세스되고 "$@"내장 set --매개변수를 사용하여 설정됩니다. 보다 정확하게는 현재 호출 스택에 각 함수 인스턴스에 대한 배열이 있지만 어느 지점에서든 현재 함수(또는 함수 외부인 경우 스크립트)의 위치 인수 배열에만 액세스할 수 있습니다. 따라서 이 배열을 사용하고 싶지만 스크립트의 매개변수를 손상시키고 싶지 않다면 함수에서 작업하세요.

~처럼sml이 언급되었습니다-F, grep 옵션을 사용하여 파일 라인당 하나의 패턴을 읽도록 하면 grep의 특정 사용 사례를 더 간단하게 해결할 수 있습니다 . 그러나 grep -F.

set -- -a -b
while IFS= read -r line; do
  set -- -e "$line"
done < "$dictionary"
mycommand "$@" more stuff

이것은 ... 불리운다 mycommand -a -b line1 line2 … more stuff.

eval여러 파일 이름 목록(또는 임의의 내용이 포함된 다른 문자열)을 조작해야 하는 경우 신중하게 사용하고 매우 신중하게 인용하면 됩니다. 엄격한 인용은 까다롭습니다. 다음 함수는 두 개의 매개변수, 즉 변수 이름과 문자열을 사용하며, 인용된 문자열 형식을 변수에 추가합니다. 인용된 형식은 작은따옴표로 묶인 리터럴이며, 작은따옴표는 적절하게 이스케이프 처리되어 쉘 구문 분석에 적합합니다.

append_to_quoted_list () {
  set -- "$1" "$(printf %s. "$2" | sed "s/'/'\\\\''/")"
  eval "$1=\"\${$1} '${2%?}'\""
}

다음은 동시에 두 개의 목록을 작성하는 사용 예입니다. $command1options 에 인수로 전달된 행을 사용하여 호출된 다음 -e해당 $command2행을 --foo=…옵션으로 전달합니다.

list1= list2=
append_to_quoted_list list1 "$command1"
append_to_quoted_list list1 "$command2"
while IFS= read -r line; do
  append_to_quoted_list list1 -e
  append_to_quoted_list list1 "$line"
  append_to_quoted_list list2 "--foo=$line"
done < "$dictionary"
eval "$list1; $list2"

관련 정보