패턴을 통해 매개변수를 구문 분석 하려고 합니다 recursive descent
.
이러한 문은 각 실행 후에 다음 단계를 수행하기 위해 while
함수를 호출합니다 .eat!
$current_token
이제 문제는 무한 루프에 들어간다는 것입니다.
정확하게 말하면 함수에는 두 개의 while 루프가 있습니다.
복합어가 문법적으로(또는 논리적으로?) 잘못되었기 때문에 둘 중 하나 또는 둘 다 작동하지 않습니다.
여러 수준에서 발생할 수 있는 문제에 대해 다음 코드를 확인해 주시겠습니까?
1)
while $(isWord? $current_token) || ! $(isVersionNumber? $current_token) && ! $(endOfInput?); do
while isVersionNumber? $current_token && ! endOfInput?; do
또 무엇이 옳은가요? 명령 대체에 검사 기능을 추가하시겠습니까?
단락으로 인해 endOfInput?
테스트도 방지되지 않습니까?
왜냐하면 그것은 분명히 주기를 멈춰야 하기 때문입니다.
이르카츄의 부탁으로
테스트 기능 코드:
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
if [[ $1 =~ $pattern ]]; then
echo true
else
echo false
fi
}
isVersionNumber? () {
local pattern="^[0-9]{1,2}(\.[0-9]{,2})*$"
if [[ $1 =~ $pattern ]]; then
echo true
else
echo false
fi
}
EO_ARGS=1
function endOfInput? {
if [ $current_token_index -ge $ARGC ]; then
EO_ARGS=0
fi
echo $EO_ARGS
}
명령 대체에 사용하고 있기 때문에 다른 명령을 출력한다고 가정합니까?
아니요, 명령 대체를 사용하지 않고 조건부로 함수를 호출하는 것이 가능한지 모르기 때문에 이것은 단지 시도일 뿐입니다.
eat!
완벽함을 위해 이 기능 도 추가했습니다 .
eat! () {
if [[ ! $(($current_char_index + 1)) -gt $ARGC ]]; then
current_token=${ARGV[$current_token_index]}
((current_token_index += 1))
current_char=${current_token:0:1}
}
test
/ [
( )를 사용하면 조건을 [[
더 잘 표현할 수 있을까요?
느낌표가 실패 지점이 될 수 있습니까?
다음은 구문상 잘못된 것 같습니다.
while [ endOfInput -eq 1 ] && isWord? "$current_token" || ! isVersionNumber? "$current_token"; do
괄호에서 [
오류 메시지가 나타납니다.
[: endOfInput: integral expression expected (translation)
답변1
함수가 true인 경우 0을 반환하고 false인 경우 다른 값을 반환하는 경우 직접 사용할 수 있습니다.
my-true () {
return 0
}
while my-true ; do
echo Infinite loop...
done
false는 아무것도 출력하지 않지만 true는 뭔가를 출력하는 경우 명령 대체를 사용하십시오.
my-true () {
echo OK
}
while [ "$(my-true)" ] ; do
echo Infinite loop...
done
전자의 경우 함수를 연결하려면 &&
및 ||
연산자를 사용할 수 있습니다.
while func1 && func2 ; do
후자의 경우 대신 연결을 사용할 수 있습니다 ||
.
while [ "$(func1 ; func2)" ] && [ "$(func3)" ]
후자의 경우 서브셸에서 호출되기 때문에 함수의 전역 변수를 수정할 수 없습니다.
그런데 함수 이름에 사용하는 것은 ?
금지되지 않지만 와일드카드이므로 문제가 발생할 수 있습니다.
abc? () {
return $1
}
abc? 0 # Everything OK.
touch abcX
abc? 0 # line 9: ./abcX: Permission denied
abc\? 0 # This works, but where's the charm?
!
기본 역사적 확장 문자이지만 주로 대화형 셸에만 관련됩니다.
답변2
여러 수준에서 발생할 수 있는 문제에 대해 다음 코드를 확인해 주시겠습니까?
좋아요
또 무엇이 옳은가요? 명령 대체에 검사 기능을 추가하시겠습니까?
명령 대체는 내부 명령을 사용합니다.인쇄, 명령줄에 입력합니다. (분할 및 글로빙 후 확장이 인용되지 않은 경우.) 따라서
foo() {
echo true
}
if $(foo); then
echo hello
fi
그런 다음 명령 대체가 생성되어 true
-문의 조건부 부분에서 실행되며 if
해당 종료 상태를 사용하여 기본 분기가 실행되었는지 확인합니다 if
. 이 경우에는 그렇습니다.
그러나 이것은 어리석은 일입니다. 명령 대체(Bash에서는 포크가 포함됨)를 거치지 않고 직접 종료 상태를 반환할 수 있습니다.
foo() {
return 0
}
if foo; then
echo hello
fi
true
또는 마지막 명령의 종료 상태가 함수의 종료 상태로 사용되므로 end 함수를 사용할 수 있습니다 .
따라서 다음과 같이 작성할 수 있습니다.
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
if [[ $1 =~ $pattern ]]; then
return 0
else
return 1
fi
}
while isWord? "$current_token"
심지어:
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
[[ $1 =~ $pattern ]]
}
while isWord? "$current_token"
모든 일반적인 이유(예: 토큰화 및 와일드카드) 때문에 이 변수를 인용해야 합니다.
while $(isWord? $current_token) || ! $(isVersionNumber? $current_token) && ! $(endOfInput?); do
여기서 a || b && c
구성 그룹은 (a || b) && c
즉, 왼쪽에서 오른쪽으로 실행된다는 점에 유의하세요. 실제 프로그래밍 언어와는 다르게그리고연산자보다 우선순위가 높습니다.또는(즉, 그 a || (b && c)
반대가 될 것입니다). 그러니 어떤 것이 필요한지 확인해 보세요.
또한 Bash의 기본 설정을 사용하는 동안 이와 같은 이름은 isWord?
자주 문제가 되지 않을 수 있지만 여전히 glob입니다. 현재 디렉터리에 일치하는 파일이 하나 이상 있으면 해당 파일 이름으로 확장됩니다. 대신 failglob
또는 을 사용하면 nullglob
영향을 받습니다. 예를 들어 failglob
:
$ foo? () { echo hi; }
$ foo?
bash: no match: foo?
$ "foo?"
hi
전역적으로 표시되지 않도록 참조해야 합니다. Zsh에서는 일치하지 않는 glob이 기본적으로 실패합니다.
함수 이름의 마지막 문자인 느낌표는 중요하지 않습니다. 이름의 시작이나 중간에 있는 경우 쉘에 기록 확장이 활성화되어 있으면 기록 확장이 발생할 수 있습니다(대화식 쉘은 기본적으로 이를 수행하지만 스크립트는 그렇지 않습니다).
단락으로 인해 endOfInput?-테스트도 방지되지 않나요?
그런 것이 있다면 while bar && ! endOfInput?; do
그렇습니다. bar
왼쪽이 false 상태를 반환하면 결과는 다음과 같습니다.그리고알려져 있고 오른쪽으로 건너뜁니다. 마찬가지로 for ||
와 true가 반환됩니다. 이것이 &&
완료되었습니다 ||
.
그러나 질문에 어떤 맥락도 제공하지 않았습니다. 즉, 함수를 호출하지 않는 것이 왜 중요한지 설명하지 않았으므로 이 작업을 수행하는 더 좋은 방법을 생각하기가 어렵습니다.