代码是将'('与')'匹配,'{'与'}'匹配。我的问题是我所做的方式是请求 pop() 创建子 shell。有没有办法用 locale -n 或 bash 4.3> 的一些新功能来修改它?
#!/bin/bash
set -x
top=0
STACK_SIZE=4
declare -a contents
read -rp "Enter parentheses: " input
if [ -z "$input" ]; then
echo "no input"
exit 1
fi
make_empty() {
top=0
}
is_empty() {
[ "$top" -eq 0 ] && return 0 || return 1
}
is_full() {
[ "$top" -eq "$STACK_SIZE" ] && return 0 || return 1
}
push() {
if is_full; then
echo "Stack overflow"
exit 1
else
contents[$top]="$1"
((top++))
fi
}
pop() { #problematic function
if is_empty; then
echo "parentheses arent matched"
exit 1
else
((top--)) #this is the line that doesnt update $top var
echo "${contents[$top]}" #but updates local copy of top inside its subshell
fi
}
i=${#input}
while read -n 1 char; do
case $char in
} | { | \( | \));;
*) echo "wrong input"
exit 1;;
esac
((i--))
if [ "$char" == '(' ] || [ "$char" == "{" ]; then
push "$char"
elif [ "$char" == ')' ] && [ "$(pop)" != '(' ]; then #here unintentional subshell creation
echo "not nested properly"
elif [ "$char" == '}' ] && [ "$(pop)" != '{' ]; then #same here
echo "not nested properly"
elif [ "$i" -eq 0 ]; then
if is_empty; then
echo "matched"
break
else
echo "Not nested properly"
fi
fi
done <<<"$input"
输入/输出:
+ top=0
+ STACK_SIZE=4
+ declare -a contents
+ read -rp 'Enter parentheses: ' input
Enter parentheses: () #INPUT
+ '[' -z '()' ']'
+ i=2
+ read -n 1 char
+ case $char in
+ (( i-- ))
+ '[' '(' == '(' ']'
+ push '('
+ is_full
+ '[' 0 -eq 4 ']'
+ return 1
+ contents[$top]='('
+ (( top++ )) # TOP IS 1 NOW
+ read -n 1 char
+ case $char in
+ (( i-- ))
+ '[' ')' == '(' ']'
+ '[' ')' == '{' ']'
+ '[' ')' == ')' ']'
++ pop
++ is_empty
++ '[' 1 -eq 0 ']'
++ return 1
++ (( top-- )) #TOP SHOULD BE 0 AFTER THIS
++ echo '('
+ '[' '(' '!=' '(' ']'
+ '[' ')' == '}' ']'
+ '[' 0 -eq 0 ']'
+ is_empty
+ '[' 1 -eq 0 ']' #TOP IS NOT UPDATED HERE
+ return 1
+ echo 'Not nested properly'
Not nested properly
+ read -n 1 char
+ case $char in
+ echo 'wrong input'
wrong input
+ exit 1
我对代码进行了注释以查明问题所在的行。 我通过从头开始重写代码解决了这个问题,但想看看是否可以通过创建这个子 shell 来做一些事情。
有没有办法用 locale -n 或 bash 4.3> 的一些新功能来修改它?
没有。
唯一的方法是实现“进程间通信”,父进程将侦听来自子进程的消息并对其采取行动。这会是很多工作。
pop
的设计。您正在同时做两件不相关的事情:打印一些信息消息,然后使用该消息来检测
pop
的结果。后者可以使用状态代码来完成,但这意味着您应该将预期弹出的元素传递给 pop
::pop() { # unproblematic function
local expected=$1
if is_empty; then
echo "parentheses arent matched" 1>&2
return 2
else
((top--)) #this is the line that doesnt update $top var
if [[ $expected == ${contents[$top]} ]]
then
return 0
else
echo "not nested properly" 1>&2
return 1
fi
fi
fi
}
并将其用作
# Matching parentheses
declare -A matching
matching[')']='('
matching[']']='['
if [[ "(){}" == *$char* ]]; then
echo "Wrong input: $char" 1>&2
elif [ "$char" == '(' ] || [ "$char" == "{" ]; then
push "$char"
elif pop ${matching[$char]}; then
: No error with pop ...
else
: pop error ...
fi
请注意,
pop ${matching[$char]}
的语义与原始的
pop
类似,但它也会验证弹出的字符。