损坏:带有增量计数器的 For 循环中的 Elif

Posted

技术标签:

【中文标题】损坏:带有增量计数器的 For 循环中的 Elif【英文标题】:Broken: Elif in For loop with increment counter 【发布时间】:2015-10-24 23:11:31 【问题描述】:

我编写了一个简短的脚本来生成格式化字符串,用于在 macintalk 中进行音节合成。我想每 20 个音节插入一个静默,所以我编写了一个 for 循环,其中一个计数器存储在一个临时文件中,一个嵌套的 elif 语句应该在每次计数器达到 20 时添加一个静默命令。然后计数器在达到后重置20.

由于某种原因,我无法预测,只有在第一次发现条件为真时才访问 elif。换句话说:计数器第一次达到 20 时,它会插入静音命令,重置并继续循环。计数器第二次达到 20 时,elif 不会被访问,并且会继续增长,直到 $k 达到它的最大值。

有人知道为什么这段代码不起作用吗?

编辑**这里是根据受欢迎的要求稍长的摘录=)

如果您想尝试重现,这里是文件的链接: syllables_phncode.txt cbsyllindx.txt

# Load Syllables
echo ''
echo 'Opening Syllable Transcription for Victoria'
echo ''
syllfile=./syllables_phncode.txt
syllables=$(cat $syllfile)
syllarray=()
counter=0;
# Create Indexed Array of Phonological Code for Syllables
for k in $syllables
do
    echo $counter
    echo $k
    syllarray[counter]=$k
    counter=$(($counter + 1));
done
# Load syllable index for stimulus stream
indxfile=./cbsyllindx.txt
indx=$(cat $indxfile)
stream=''
tempfile=count.tmp
echo 0 > $tempfile
echo '====================================================================================='
echo 'Counter Balanced Stimulus Order (Indexed by Syllables in Alphabetical Order)'
echo '====================================================================================='
echo $indx
echo '====================================================================================='
echo ''
echo 'Creating counterbalanced stimulus stream string with proper Macintalk formatting'
echo ''
for k in $indx
do
    counter=$[$(cat $tempfile) + 1]
    echo $counter > $tempfile
    if [ $k -eq 0 ]; then
        stream=$stream'@_'$syllarray[k]
    elif [ $counter -eq 20 ]; then
    echo Adding Silence after syllable: $syllarray[k]
        stream=$stream'_'$syllarray[k]'[[ slnc 20 ]]'
        echo 0 > $tempfile
    else
        stream=$stream'_'$syllarray[k]
    fi
done
unlink $tempfile
echo '------------------------------------------------------'
echo 'Printing Stream to Screen'
echo '------------------------------------------------------'
echo $stream

这是由该脚本创建的字符串:

_tUW_dAE_rOW_pIY_gOW_lAE @ _bIY_kUW_tIY_tUW_dAE_rOW_pIY_gOW_lAE_bUW_dOW_pAE_pIY_gOW [ [slnc20]] EM> _lAE @ _bIY_kUW_tIY_tUW_dAE_rOW_bUW_dOW_pAE @ _bIY_kUW_tIY_pIY_gOW_lAE_bUW_dOW_pAE @ _bIY_kUW_tIY_pIY_gOW_lAE_tUW_dAE_rOW @ _bIY_kUW_tIY_bUW_dOW_pAE_pIY_gOW_lAE_tUW_dAE_rOW_bUW_dOW_pAE_tUW_dAE_rOW @ _bIY_kUW_tIY_bUW_dOW_pAE_pIY_gOW_lAE @ _bIY_kUW_tIY_tUW_dAE_rOW_pIY_gOW_lAE_bUW_dOW_pAE @ _bIY_kUW_tIY_pIY_gOW_lAE_tUW_dAE_rOW @ _bIY_kUW_tIY_pIY_gOW_lAE_tUW_dAE_rOW @ _bIY_kUW_tIY_bUW_dOW_pAE_pIY_gOW_lAE_bUW_dOW_pAE @ _bIY_kUW_tIY_tUW_dAE_rOW_bUW_dOW_pAE_pIY_gOW_lAE @ _bIY_kUW_tIY_bUW_dOW_pAE_tUW_dAE_rOW_bUW_dOW_pAE_tUW_dAE_rOW_bUW_dOW_pAE @ _bIY_kUW_tIY_pIY_gOW_lAE_bUW_dOW_pAE @ _bIY_kUW_tIY_tUW_dAE_rOW @ _bIY_kUW_tIY_tUW_dAE_rOW_pIY_gOW_lAE_tUW_dAE_rOW_bUW_dOW_pAE_pIY_gOW_lAE @ _bIY_kUW_tIY_bUW_dOW_pAE_tUW_dAE_rOW_pIY_gOW_lAE @ _bIY_kUW_tIY_pIY_gOW_lAE_bUW_dOW_pAE_tUW_dAE_rOW @ _bIY_kUW_tIY_bUW_dOW_pAE_pIY_gOW_lAE_tUW_dAE_rOW_pIY_gOW_lAE_bUW_dOW_pAE_tUW_dAE_rOW @ _bIY_kUW_tIY_pIY_gOW_lAE_tUW_dAE_rOW @ _bIY_kUW_tIY_pIY_gOW_l AE_tUW_dAE_rOW_bUW_dOW_pAE @ _bIY_kUW_tIY_bUW_dOW_pAE_pIY_gOW_lAE @ _bIY_kUW_tIY_bUW_dOW_pAE @ _bIY_kUW_tIY_tUW_dAE_rOW_bUW_dOW_pAE_tUW_dAE_rOW_pIY_gOW_lAE @ _bIY_kUW_tIY_tUW_dAE_rOW_pIY_gOW_lAE_bUW_dOW_pAE P>

【问题讨论】:

有什么理由不只是将计数器保存在内存中并在那里修改它,而不是在每次循环迭代时从临时文件中写入和读取它? 我一开始是这样尝试的,我得到了相同的结果。我在堆栈交换上读到,如果调用了一个子shell,那么拥有一个临时文件很有用,所以我绝望地尝试了。 对不起,如果很明显,但我看不出如何获得你得到的输出。我假设输出在变量 stream 中。您对 indxsyllarray 使用了哪些值? 感谢 David,是的 stream 是通过按 indx 指定的顺序连接 syllarray 中的音节创建的输出 -- syllarray 从带有以下字符串的文本文件中读取: bIY bUW dAE dOW gOW kUW lAE pAE pIY rOW tIY tUW; indx 是从一个包含 298 个数字的文件中读取的,这些数字指示接下来将哪些音节连接到流中,这给了我在上面帖子中看到的顺序的 298 个音节 当然!我试图使帖子尽可能简短,但我可以添加所有内容^_^ 【参考方案1】:

您的问题是,当 $counter 等于 20 时,您点击了 $k -eq 0 检查,但无论如何您都会增加计数器,然后一旦您通过 20,您将永远无法再次点击它。

您可以通过将set -x 添加到脚本顶部并运行它并查看输出来查看这一点。

你不希望 if/else 用于无关检查它有这个问题。

您可能想要更像这样的东西作为循环的主体。

if [ $k -eq 0 ]; then
    stream=$stream@
fi
stream=$stream_$syllarray[k]
if [ $counter -eq 20 ]; then
    stream=$stream'[[ slnc 20 ]]'
fi

这将关注点分开。

您也根本不需要(如 cmets 中所示)此处的临时文件。 (除了那些处理读取不重要的文件的子shell之外,您没有任何子shell。)

您也可以改用$(< file) 来避免$(cat file) 子shell。

您还应该始终使用$((...)) 而不是$[...]

【讨论】:

另外,当使用((..)) 时,不要在双括号内的变量名前包含$。例如(counter=$(($counter + 1)); 应该是 counter=$((counter + 1)) 或简单的 ((counter++))注意:在结束 )) 之后不需要续行(例如 ;)。 我尝试了这个解决方案并得到了最奇怪的输出,我之前还注意到,如果我将条件从 20 更改为 15 或其他数字,那么它会在第一次之后插入静音,但不是每次都插入这种情况是真的..我认为我的电脑是精神分裂症:-S 任何时候你有$k -eq 0 是真的你有机会跳过相关的$counter -eq X 检查。一旦你的计数器循环失败,你就跳过它。因此,对于任何给定的X,如果您曾经在其中多次点击$k -eq 0,它将在那个时候失败。该修复程序为您带来了哪些“最奇怪”的输出?

以上是关于损坏:带有增量计数器的 For 循环中的 Elif的主要内容,如果未能解决你的问题,请参考以下文章

php循环语句

带循环的增量计数器

带有增量的 Swift 3 for 循环

带有 for 循环的 goto() 函数

15PHP 循环 - For 循环

R中的for循环,增量