在 bash 中的函数内操作全局变量的问题

问题描述 投票:0回答:2

代码是将'('与')'匹配,'{'与'}'匹配。我的问题是我所做的方式是请求 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 来做一些事情。

bash function stack subshell
2个回答
0
投票

有没有办法用 locale -n 或 bash 4.3> 的一些新功能来修改它?

没有。

唯一的方法是实现“进程间通信”,父进程将侦听来自子进程的消息并对其采取行动。这会是很多工作。


0
投票
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
类似,但它也会验证弹出的字符。
    

© www.soinside.com 2019 - 2024. All rights reserved.