首页 > 解决方案 > 变量超出条件的 Bash

问题描述

我需要编写一个脚本来完成从 1 到 的所有排列,我的脚本参数n在哪里。n出于某种原因,我无法让它在 bash 中运行,程序逻辑应该很好,因为它在 C 中运行良好。所以我假设我犯了某种与 bash 相关的错误。如果我回应i它似乎超过了for身体的状况,我猜这是问题,但我不知道为什么。

前任:n = 3

123
132
213
231
312
321

这是我的代码

#! /bin/bash

n=$1
a=()
used=( $(for i in $(seq $n);do echo 0;done) )
function show
{
    v=("$@")
    for i in ${v[@]}; do
        printf "%d " $i
    done
    printf "\n"
}

function backtracking
{
    if [ $1 -eq $((n+1)) ]
    then
        show ${a[@]}
    else
        for ((i=0;i<$n;i++));do
            if [ "${used[$i]}" -eq 0 ]
            then
                a[$(($1-1))]=$(($i+1))
                used[$i]=1
                backtracking $(($1+1))
                used[$((i))]=0
            fi
            done
    fi
}


backtracking 1

exit 0

标签: linuxbashshell

解决方案


请阅读 Bash 中的局部变量:https ://tldp.org/LDP/abs/html/localvar.html

#!/usr/bin/env bash

n=$1
a=()
used=( $(for _ in $(seq $n);do echo 0;done) )
function show
{
    v=("$@")
    local i
    for i in ${v[@]}; do
        printf "%d " $i
    done
    printf "\n"
}

function backtracking
{
    local index="$1"

    if [ "$index" -eq $((n+1)) ]
    then
        show ${a[@]}
    else
        local i
        for ((i=0;i<$n;i++));do
            if [ "${used[$i]}" -eq 0 ]
            then
                a[$((index-1))]=$((i+1))
                used[$i]=1
                backtracking $((index+1))
                used[$i]=0
            fi
            done
    fi
}


backtracking 1

而且你的脚本中有很多不好的做法。去看看https://www.shellcheck.nethttps://github.com/bash-lsp/bash-language-server,它们很棒。

这是一个更清洁的版本:

#!/usr/bin/env bash

width="$1"
mapfile current < <( for _ in $( seq 0 $(( width - 1 )) ); do printf '0\n'; done )

function backtracking {
    local index="$1"

    if [[ "$index" -eq "$width" ]]; then
        for bit in "${current[@]}"; do
            printf '%d ' "$bit"
        done
        printf '\n'
    else
        local i
        for (( i = 1; i <= "$width"; i++ )); do
            local used=0
            local j
            for (( j = 0; j < "$1"; j++ )); do
                if [[ "${current[$j]}" -eq "$i" ]]; then
                    used=1
                    break
                fi
            done
            if [[ "$used" -eq 1 ]]; then
                continue
            fi
            current[$index]="$i"
            backtracking $(( index + 1 ))
        done
    fi
}

backtracking 0

推荐阅读