【问题标题】:Creating a bash script that acts as a fortune teller or "magic 8 ball" essentially创建一个基本上充当算命先生或“魔术 8 球”的 bash 脚本
【发布时间】:2012-12-03 01:09:16
【问题描述】:

我正在尝试创建一个 bash 脚本,它本质上就像一个具有 6 种不同响应(是、否、可能、很难说、不太可能和未知)的魔术 8 球。关键是一旦给出了响应,在所有响应都给出之前不应再次给出。

这是我目前所拥有的:

#!/bin/bash
echo "Ask and you shall receive your fortune: "
n=$((RANDOM*6/32767))
while [`grep $n temp | wc awk '{print$3}'` -eq 0]; do
   n=$((RANDOM*6/32767))
done
grep -v $n temp > temp2
mv temp2 temp

基本上,我在临时文件的不同行上有 6 个响应,我正在尝试构建循环,以便一旦给出响应,它会创建一个没有该响应的新文件 (temp2),然后将其复制回来到温度。然后一旦临时文件为空,它将从头开始。

我非常肯定我当前的内部循环是错误的,我需要一个外部循环,但我对此很陌生,我被卡住了。

任何帮助将不胜感激。

【问题讨论】:

  • 感谢 h3nr1x 清理格式。我最初以正确的格式提交了问题,但由于某些原因导致它变得杂乱无章。
  • 别担心,我现在正在尝试运行您的脚本
  • 能否请您发布temp 文件内容?我正在尝试使用这种格式,但正如我所见,它看起来有 3 列,对吧?
  • 它有各自的响应,编号为一行,如下所示:1 是 2 否
  • 对不起,我没有意识到点击回车提交评论,但每个响应都在自己的行上,行编号。它没有在 cmets 中单独显示,但如果不清楚,我可以发布一个屏幕截图给你看。

标签: bash loops scripting


【解决方案1】:

试试这样的:

#!/bin/bash

shuffle() {
   local i tmp size max rand

   # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
   # Compensate by using a range which is a multiple of the array size.
   size=${#array[*]}
   max=$(( 32768 / size * size ))

   for ((i=size-1; i>0; i--)); do
      while (( (rand=$RANDOM) >= max )); do :; done
      rand=$(( rand % (i+1) ))
      tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp
   done
}

array=( 'Yes' 'No' 'Maybe' 'Hard to tell' 'Unknown' 'Unlikely' )

shuffle
for var in "${array[@]}"
do
  echo -n "Ask a question: "
  read q
  echo "${var}"
done

【讨论】:

  • 感谢您的回答。运行后,输出是所有 6 个响应。我的目标是让用户输入一个每次会收到一个响应的问题。
  • 它完美无瑕。一旦给出了所有 6 个响应,脚本就会停止。完成所有 6 项后,是否可以从头开始继续所有响应?
  • 感谢迭戈的帮助。
【解决方案2】:

我按照您的初始方法编写了一个脚本(使用临时文件):

#!/bin/bash

# Make a copy of temp, so you don't have to recreate the file every time you run this script
TEMP_FILE=$(tempfile)
cp temp $TEMP_FILE

# You know this from start, the file contains 6 possible answers, if need to add more in future, change this for the line count of the file
TOTAL_LINES=6

echo "Ask and you shall receive your fortune: "
# Dummy reading of the char, adds a pause to the script and involves the user interaction
read

# Conversely to what you stated, you don't need an extra loop, with one is enough
# just change the condition to count the line number of the TEMP file 
while [ $TOTAL_LINES -gt 0 ]; do
    # You need to add 1 so the answer ranges from 1 to 6 instead of 0 to 5
    N=$((RANDOM*$TOTAL_LINES/32767 + 1))

    # This prints the answer (grab the first N lines with head then remove anything above the Nth line with tail)
    head -n $N < $TEMP_FILE | tail -n 1

    # Get a new file deleting the $N line and store it in a temp2 file
    TEMP_FILE_2=$(tempfile)
    head -n $(( $N - 1 )) < $TEMP_FILE > $TEMP_FILE_2
    tail -n $(( $TOTAL_LINES - $N )) < $TEMP_FILE >> $TEMP_FILE_2
    mv $TEMP_FILE_2 $TEMP_FILE

    echo "Ask and you shall receive your fortune: " 
    read

    # Get the total lines of TEMP (use cut to delete the file name from the wc output, you only need the number)
    TOTAL_LINES=$(wc -l $TEMP_FILE | cut -d" " -f1)
done

【讨论】:

  • 不客气,在解释步骤的代码中添加了一些 cmets
  • 非常接近,但是一旦输入问题的第一个字母,就会在第一个字符之后立即打印响应,中间没有空格,然后会提示另一个问题。
  • 好吧,很简单,把read命令中的-N 1部分去掉,我来更新答案
  • 刚更新重跑,第一个问题还是出现问题,之后就没有了。
【解决方案3】:
$ man shuf

SHUF(1)                                                           User Commands

NAME
       shuf - generate random permutations

SYNOPSIS
       shuf [OPTION]... [FILE]
       shuf -e [OPTION]... [ARG]...
       shuf -i LO-HI [OPTION]...

DESCRIPTION
       Write a random permutation of the input lines to standard output.

后面有更多内容,你可以在自己的机器上阅读:)

【讨论】:

    猜你喜欢
    • 2019-04-01
    • 1970-01-01
    • 2017-01-26
    • 2011-10-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多