내가 읽고 있는 책 - O'Reilly의 Bash Shell 학습에서는 다음과 같이 일부 코드를 지정합니다.
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
howmany=$1
shift
....
....
etc
이는
grep
검색 유틸리티를 사용하여$1
적절한 패턴이 일치하는지 테스트합니다. 이를 위해 우리는^-[0-9][0-9]*$
"첫 글자에 대시와 숫자, 선택적으로 하나 이상의 숫자가 뒤따르는"로 해석되는 정규식을 grep에 제공합니다. 일치하는 항목이 발견되면grep
일치 항목이 반환되고 테스트는 true가 됩니다. 그렇지 않으면 아무것도 반환되지 않고 처리가 테스트grep
로 전달됩니다 .elif
쉘이 $ 및 *를 해석하고 이를 수정되지 않은 상태로 grep에 전달하는 것을 방지하기 위해 정규식을 작은따옴표로 묶었습니다.
그렇다면 정규 표현식이 '^-[0-9]'
작은 따옴표처럼 의미를 잃지 않는 이유는 무엇입니까? 일반적으로 작은 따옴표 안의 모든 내용은 의미를 잃습니다.
당신의 도움을 주셔서 감사합니다.
답변1
다른 사람들이 귀하의 특정 질문에 이미 답변했지만 추가하겠습니다.
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
이는 여러 가지 이유로 문자열이 정규 표현식과 일치하는지 확인하는 나쁜 방법입니다.
echo
임의의 데이터 와 함께 사용할 수 없습니다- 위와 같이 매개변수 확장을 따옴표로 묶지 않은 상태로 두는 것은
$1
분할+글로브 연산자입니다. grep
전체 입력에 대해 정규식을 일치시키는 대신 입력의 각 줄을 일치시킵니다. 예를 들어 true 를 반환합니다foo\n-0\nbar
.- 정규식은 길이가 0과 일치할 수 있으므로
grep
일반적인 경우에 일부 출력을 생성하는지 확인하는 것은 잘못된 것입니다(명령 대체는 후행 줄 바꿈을 제거한다는 점에 유의하십시오).grep -q
의 종료 상태를 사용하고 의존하는 것이 더 좋으며 명령 대체도 피하는 것이 좋습니다.grep
[
- 명령은 다음과 같이
grep
단순화될 수 있습니다.grep -xE '-[0-9]+'
bash
, (확장된) 정규식 일치를 위한 전용 연산자가 있습니다 ksh93
. zsh
세 가지 모두(bash-3.1 포함)에서 이식 가능하고 안정적으로 사용하려면 구문은 다음과 같습니다.
re='^-[0-9]+$'
if [[ $1 =~ $re ]]; then
echo matches
fi
yash
또한 zsh
다음을 지원합니다.
if [ "$1" '=~' '^-[0-9]+$' ]; then
echo matches
fi
문자열(기본) 정규식 일치를 위한 표준 명령은 다음과 같습니다 expr
.
if expr " $1" : ' -[0-9]\{1,\}$' > /dev/null; then
echo matches
fi
^
(는 아님 $
) 은 에 암시 적으로 포함되어 있습니다 expr
. 또한 연산자 $1
로 사용되는 값에 대한 문제를 피하기 위해 선행 공백 문자를 사용합니다 expr
.
또한 정규 표현식이 포함되면 \(...\)
동작에 영향을 미칩니다 expr
.
대체로 awk
이를 달성하려면 다른 표준/이식 가능한 방법을 사용하는 것이 더 좋습니다( awk
확장 정규식 사용에 유의하세요).
if STRING=$1 RE='^-[0-9]+$' awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'; then
...
또는 다음 기능을 사용하세요.
re_match() {
STRING=$1 RE=$2 awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'
}
if re_match "$1" '^-[0-9]+$'
이 경우 표준 case
구성을 사용하여 이를 달성할 수도 있습니다.
case $1 in
("" | *[!0-9-]* | [!-]* | - | ?*-*) ;;
(*) echo match;;
esac
를 사용하려면 옵션(지원되는 경우 표준 옵션이 아니기 때문에)과 함께 사용하여 개행으로 구분된 레코드 대신 NUL로 구분된 레코드를 처리하도록 지시할 수 있습니다 grep
. --null
대부분의 쉘에서는 $1
NUL을 포함할 수 없으므로 안전합니다.
if printf %s "$1" | grep --null -xq '-[0-9]+$'; then
echo match
fi
답변2
작은따옴표는 셸에 포함된 문자를 그대로 두도록 지시합니다.설명이 없다. 인용된 문자열은 인용부호 없이 있는 그대로 전달됩니다 grep
. grep
인수를 검색할 때 다음과 같이 표시됩니다.
grep
그리고
^-[0-9][0-9]*$
그리고 그에 따라 행동하십시오. (읽다프로그램 작동 방식리눅스에서의 매개변수 구성이 궁금하시다면. )
bash
그리고 grep
그것은 다릅니다. 이 명령은 따옴표를 사용하여 bash
문자열이 처리되지 않고 grep
문자열이 처리되도록 합니다.
답변3
작은따옴표 방지와일드카드( bash
와일드카드를 이렇게 해석하도록 함 *
) 그리고 변수 확장을 사용합니다 $
. 기본적으로 bash
"문자 그대로 이 문자를 가져와서 전달합니다 " 라고 말하는 것입니다 grep
. 보시면 grep
정규식을 이해할 수 있게 만들어져 있으니그 다음에정규식은 내부적으로 해석됩니다 grep
.
더 짧은 버전: 작은따옴표로 묶인 인수는 인수가 명령에 전달되기 전에 셸 처리를 이스케이프하는 방법을 제공합니다.
답변4
실제로 그 의미를 잃었습니다. grep
bash와 거의 동일한 정규식 패턴을 사용합니다.