【问题标题】:Using a variable as another variable in a bash script?在 bash 脚本中使用一个变量作为另一个变量?
【发布时间】:2014-08-26 14:29:50
【问题描述】:

您好,我是 bash 脚本的新手,在编写我自己的脚本时技术不是很熟练,我有一个可以在终端中完美运行的脚本。我想用 zenity 让事情变得简单、直接(但也作为一个小学习项目)。

脚本生成随机密码,zenity 是一个很好的小工具。

虽然我遇到了一个问题,脚本作为 GUI 运行良好,但是当我想介绍一种让用户选择密码长度的方法时,它无法生成密码。 让用户输入所需数字(密码长度)的代码:

number=32
zenity --entry --text="Please enter a number (no limitations!) :" --entry-text="$number"

read newnumber

[ -n "$newnumber" ] && number=$newnumber

如果在终端中运行,则会显示在终端中输入的数字,而不是在 zenity 框中。我不能使用变量...:

number=$newnumber

...稍后在脚本中根据需要更改了一个变量:

LENGTH="32"

收件人:

LENGTH="$newnumber"

脚本作为 GUI 正常运行(除了不产生密码),但在我得到的终端中(如果用户输入数字 25):

25

/home/server/Desktop/passwd32gen: line 22: [: : integer expression expected

因此,我使用$newnumber 作为LENGTH= 变量中的值破坏了脚本的生成部分。我自己尝试了各种不同的方法来解决这个问题,但知道的太多了,我认为这将是一个非常简单的语法缺失部分(或者我只是希望如此)。

现在我正在努力解决这个问题,我已经尝试过

declare

eval

以多种方式,但它们似乎破坏了脚本。

提前感谢任何可以提供帮助的人!

请记住,我正在寻找一种方法来使用 zenity 来允许用户选择正在生成的密码的长度。

整个脚本是:

    #!/bin/bash
    # May need to be invoked with  #!/bin/bash2  on older machines.
    #
    #Random 32 character password generator
    #
    zenity --info --title="32 Character Password Generator" --text="Hi, so you want to get yourself a new password? You've the perfect little application here, just click OK to generate your new password."

    number=32
    zenity --entry --text="Please enter a number (no limitations!) :" --entry-text="$number"
    read newnumber
    [ -n "$newnumber" ] && number=$newnumber

    MATRIX="0123456789<?/_+-!@#$%^&*>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    #  Password will consist of standard characters.
    LENGTH="$newnumber"
    #This variable can be changed for password lenth (need to try get zenity to let user choose that number)


    while [ "${n:=1}" -le "$LENGTH" ]
    # := is "default substitution" operator.
    # So, if 'n' has not been initialized, set it to 1.
    do
    PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
    # Very clever, but tricky.

    # Starting from the innermost nesting...
    # ${#MATRIX} returns length of array MATRIX.

    # $RANDOM%${#MATRIX} returns random number between 1
    # and [length of MATRIX] - 1.

    # ${MATRIX:$(($RANDOM%${#MATRIX})):1}
    # returns expansion of MATRIX at random position, by length 1. 
    # See {var:pos:len} parameter substitution in Chapter 9.
    # and the associated examples.

    # PASS=... simply pastes this result onto previous PASS (concatenation).

    # to let zenity show the password being built one character at a time, uncomment the following line
    # zenity --info --text="$PASS"
    let n+=1
    # Increment 'n' for next pass.
    done

    zenity --info --title="Your 32 character password" --text="Here is your random 32 character password, you can copy and paste it wherever you wish...


    $PASS



    The passwords generated by this application are very strong, here are the numbers;

    Length:                  32 characters
    Character Combinations:  96
    Calculations Per Second: 4 billion
    Possible Combinations:   2 vigintillion

    Based on an average Desktop PC making about 4 Billion calculations per second

    It would take about 21 quattuordecillion years to crack your password.

    As a number that's 21,454,815,022,336,020,000,000,000,000,000,000,000,000,000,000 years!"      # you could redirect to a file, to store the password. Use something like $PASS 2> /file/name

    exit 0

【问题讨论】:

  • 对于标题中提出的字面问题(使用间接变量),请参阅 BashFAQ #6:mywiki.wooledge.org/BashFAQ/006 - 但是,这似乎与您的实际问题无关。
  • 另外,set -x 是你的朋友; bash -x yourscript 将在执行时向您显示每一行,因此您可以准确找出问题所在,并将此问题缩减为仅包含显示问题所需的最低限度。
  • ...请参阅stackoverflow.com/help/mcve,了解有关提出易于回答问题的一些指南。
  • 快说吧,我现在去看看,谢谢
  • 使用 bash -x 似乎做了一些好事,我发现脚本卡在 zenity --entry,所以我尝试了下面的答案,它已经工作了谢谢。

标签: linux bash shell zenity


【解决方案1】:

您的 zenity 命令后面的 read 命令不会从 zenity 读取 - 它仍然像往常一样从标准输入读取。

相反,您可能想要:

newnumber=$(zenity --entry \
  --text="Please enter a number (no limitations!) :" \
  --entry-text="$number")

...无需遵循read 命令。

也就是说,如果您确实出于某种原因想要使用read,您仍然可以这样做:

read -r newnumber < <(zenity --entry \
  --text="Please enter a number (no limitations!) :" \
  --entry-text="$number")

【讨论】:

  • 这两个都工作了几次,但是当我尝试不同的数字时,脚本现在变得不稳定,我导致了我原来的问题,我尝试以各种方式实现它们,但没有生成密码.
  • (zenity:3861): Gtk-WARNING **: cannot open display: :0.0 + number=32 + read -r newnumber ++ zenity --entry '--text=请输入一个数字(没有限制!):' --entry-text=32 没有指定协议(zenity:3863):Gtk-WARNING **:无法打开显示::0.0 + MATRIX='0123456789/_+-!@#$ %^&*>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + LENGTH= + '[' 1 -le '' ']' passwd32gen: line 23: [: : integer expression expected
  • @JackHerer,这是您的 X 配置问题,而不是 bash 问题。
  • 如果我选择生成 10 个字符,它可以工作.....15 它可以工作....20 它不会工作.....15 它不会工作....10 它可以工作。 ...15 有效....20 无效....10 有效!!!你有没有机会知道它为什么能做到这一点?
  • 我的 X 配置会怎样?
【解决方案2】:

如果您真的希望能够显示特殊字符,可以使用 zenity --text-info 如下所示。这在美学上并不令人愉悦,但可以做到。

再花 2 美分

echo "Here is your random $newnumber character password, you can copy and paste it wherever you wish...


$PASS


The passwords generated by this application are very strong, here are the numbers;

Length:                  $newnumber characters
Character Combinations:  96
Calculations Per Second: 4 billion
Possible Combinations:   2 vigintillion

Based on an average Desktop PC making about 4 Billion calculations per second

It would take about 21 quattuordecillion years to crack your password.

As a number that's 21,454,815,022,336,020,000,000,000,000,000,000,000,000,000,000 years!" | zenity --text-info --title "Your $newnumber character password" --width 600 --height 500`

附录,

在玩了一段时间之后,zenity 似乎不喜欢打印带有特殊字符的变量。

这个脚本应该可以工作

我做了 2 处更改。

1 newnumber=`zenity.... 这将从 zenity 读取输入。

2 从 MATRIX 中删除了一些特殊字符

我用#CHANGED标记了所有更改

这是修改后的脚本。

#!/bin/bash
# May need to be invoked with  #!/bin/bash2  on older machines.
#
#Random 32 character password generator
#
zenity --info --title="32 Character Password Generator" --text="Hi, so you want to get yourself a new password? You've the perfect little application here, just click OK to generate your new password."

number=32
# CHANGED
newnumber=`zenity --entry --text="Please enter a number (no limitations!) :" --entry-text="$number"`
# read newnumber
[ -n "$newnumber" ] && number=$newnumber
#CHANGED Removed offending special characters
MATRIX="0123456789?_+-!$%^>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#  Password will consist of standard characters.
LENGTH="$newnumber"
#This variable can be changed for password lenth 
#(need to try get zenity to let user choose that number)


while [ "${n:=1}" -le "$LENGTH" ]
# := is "default substitution" operator.
# So, if 'n' has not been initialized, set it to 1.
do
PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
# Very clever, but tricky.

# Starting from the innermost nesting...
# ${#MATRIX} returns length of array MATRIX.

# $RANDOM%${#MATRIX} returns random number between 1
# and [length of MATRIX] - 1.

# ${MATRIX:$(($RANDOM%${#MATRIX})):1}
# returns expansion of MATRIX at random position, by length 1. 
# See {var:pos:len} parameter substitution in Chapter 9.
# and the associated examples.

# PASS=... simply pastes this result onto previous PASS (concatenation).

# to let zenity show the password being built one character at a time, uncomment the following line
# zenity --info --text="$PASS"
let n+=1
# Increment 'n' for next pass.
done
# CHANGED $PASS to '$PASS' below
zenity --info --title="Your 32 character password" --text="Here is your random 32 character password, you can copy and paste it wherever you wish...


$PASS



The passwords generated by this application are very strong, here are the numbers;

Length:                  32 characters
Character Combinations:  96
Calculations Per Second: 4 billion
Possible Combinations:   2 vigintillion

Based on an average Desktop PC making about 4 Billion calculations per second

It would take about 21 quattuordecillion years to crack your password.

As a number that's 21,454,815,022,336,020,000,000,000,000,000,000,000,000,000,000 years!"      # you could redirect to a file, to store the password. Use something like $PASS 2> /file/name

exit 0

【讨论】:

  • 谢谢它和@Charles 的回答一样好用,除了我觉得对 $PASS 变量使用单引号不会改变任何东西,但会导致问题,因为单引号显示在对话框中,所以密码复制时总是要长两个字符。
  • 对不起,我确实从变量中删除了单引号,但我在更新脚本时忘记删除注释。这是导致问题的特殊字符。
  • 删除特殊字符是怎么回事? bash 可以从字面上表示字符串中除 NUL 之外的任何 ASCII 字符,即使它需要一点小心。
  • @MPH426 你已经回答了我的问题,删除字符 @#&* 已经奏效,显然它在尝试生成和理解这些字符时遇到了困难。如果有人知道,解释为什么它不喜欢这些角色会很好?
  • 不是 bash 的特殊字符有问题。 Zenity 似乎是罪魁祸首。如果您删除所有对 zenity 的引用并将其编码为直接的 bash 脚本,您将不会遇到同样的问题。我用 PHP 和其他语言遇到过几次。在某些情况下,您不能使用某些字符。例如,我的 ISP 的登录将不允许 !出于某种原因的符号。
猜你喜欢
  • 1970-01-01
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
  • 2018-02-01
  • 1970-01-01
相关资源
最近更新 更多