grep
실행된 명령에 해당 cmd
단어가 name
인수로 포함되어 있는지 확인하는 데 사용하고 싶습니다 . (Bash에 대해 알고 있지만 !*
사용하고 싶지 않습니다.)
라는 변수에 명령이 있다고 가정해 보겠습니다 process
.
처음에는 echo $process | grep 'cmd name'
. 이는 하나의 인수만 고려하기 때문에 충분히 정제되지 않았습니다.
그래서 정규식을 사용하여 마지막 인수로 캡처할 수 있는지 확인하려고 했습니다 cmd .*(?= )name
. 아이디어는 무엇이든 캡처하고 그 뒤에 공백이 오고 그 뒤에 name
(뒤에 cmd
) 오는 것입니다. 그러나 이것은 작동하지 않습니다.
내 목표는 이것이 효과가 있었다면 그것이 어떤 입장에서든 논쟁이 될 수 있는지 설명하는 것이었습니다.
이를 위해 정규 표현식을 어떻게 사용할 수 있나요?
답변1
아래 답변에서는 grep
. 명령줄은 개별 항목의 목록이므로 텍스트 줄이 아니라 그 자체로 구문 분석되어야 합니다.
명령과 명령 인수를 모두 단일 문자열로 유지한다고 가정하면(배열을 사용하는 것이 더 나을 것입니다.변수에 저장된 명령을 어떻게 실행할 수 있나요?) 그러면 다음과 같은 작업을 수행할 수 있습니다.
process='cmd with "some arguments" and maybe name'
set -f
set -- $process
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
$process
이렇게 하면 먼저 파일 이름 생성이 비활성화됩니다 . 인용되지 않은 파일을 별도의 단어로 분할하기 위해 사용 하고 해당 문자열에 파일 이름 글로빙 패턴(예 *
: )이 포함되어 있으면 구문 분석이 엉망이 되기 때문입니다. 우리는 이것을 set -f
.
그런 다음 위치 매개변수를 의 단어로 설정합니다 $process
. 그 후에 "$1"
is 인 경우 나머지 명령줄에서 cmd
검색해야 한다는 것을 알 수 있습니다 . name
그렇지 않다면 거기서 멈추겠습니다.
위치 매개변수 목록에서 shift
벗어나 루프 의 인수를 살펴보기 시작합니다. cmd
각 반복에서 인수를 문자열과 비교하기만 하면 됩니다 name
. 찾으면 그렇게 말하고 종료합니다.
루프가 끝나면 name
인수를 찾지 못했다는 것을 알게 되므로 이를 보고하고 실패로 종료합니다.
위의 예에서 인수는 some arguments
두 가지로 구문 분석됩니다.분리된"some
이는 명령 arguments"
과 해당 인수를 단일 문자열에 저장하고 싶지 않은 이유 중 하나입니다. 이는 또한 name
단일 인수 내부의 인수를 감지한다는 의미이며 "some name string"
, 이는 거짓 긍정이 됩니다.
명령줄이 배열(예: bash
)에 저장되어 있는 경우 다음과 같이 할 수 있습니다.
process=( cmd with "some arguments" and maybe name )
if [ "${process[0]}" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
for arg in "${process[@]:1}"; do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
확장은 "${process[@]:1}"
전체 배열이지만 첫 번째 항목(명령 이름)은 아닙니다.
/bin/sh
(and dash
및 기타 POSIX 셸) 의 경우 bash
위의 내용이 덜 장황합니다.
set -- cmd with "some arguments" and maybe name
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
이는 기본적으로 첫 번째 코드 조각과 동일하지만 명령줄의 모든 요소를 단일 텍스트 문자열로 결합하지 않기 때문에 모든 인수(인용 등)를 올바르게 처리합니다.
답변2
bash를 언급했으므로 또 다른 옵션은 패턴 일치 연산자입니다 =~
.
if [[ $process =~ ^cmd[[:space:]].*name([[:space:]]|$) ]]
then
_name_ was found as an argument to _cmd_
fi
cmd
이는 변수의 내용이 로 시작하고 , 공백이 뒤따르고, 아무 것도 아니면 아무것도 뒤따르지 않고, 그 뒤에 name
공백이나 줄의 끝이 오는지 확인합니다 .