현재 디렉토리에서 여러 단어를 검색하고 싶습니다. 이를 달성하기 위해 나는 이와 같은 것을 사용합니다.
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%?}'\""
}
다음은 동시에 두 개의 목록을 작성하는 사용 예입니다. $command1
options 에 인수로 전달된 행을 사용하여 호출된 다음 -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"