如果没有任何命令行参数,我希望此函数返回一个随机单词。
我正在修改 linuxconfig.org 的随机字生成器,使其即使在 #$ -ne 1 时也可以运行。
function random-word {
if [ $# -eq 0 ] ;
then
echo "I only take one argument, dummy"
# previously was exit 0
fi
# Constants
X=0
ALL_NON_RANDOM_WORDS=/usr/share/dict/words
# total number of non-random words available
non_random_words=`cat $ALL_NON_RANDOM_WORDS | wc -l`
# while loop to generate random words
# number of random generated words depends on supplied argument
while [ $X -lt "$1" ]
do
random_number=`od -N3 -An -i /dev/urandom |
awk -v f=0 -v r="$non_random_words" '{printf "%i\n", f + r * $1 / 16777216}'`
sed `echo $random_number`"q;d" $ALL_NON_RANDOM_WORDS
let "X = X + 1"
done
该语句执行,但出现 bash 错误:
$ bob
I only take one argument, dummy
bash: [: : integer expression expected
如何修复此问题以便不会显示 bash 错误?
答案1
while [ $X -lt "$1" ]
即使没有 1 美元也会被评估。
将其余代码移至 else 块中,这样就不会发生这种情况。
function random-word {
# from linuxconfig.org
if [ $# -eq 0 ]
then
echo "I need an argument, dummy"
# To be extra friendly, give them a random word.
echo "Here's a random word:"
random-word 1
else
# Constants
X=0
...
sed `echo $random_number`"q;d" $ALL_NON_RANDOM_WORDS
let "X = X + 1"
done
fi
}
答案2
你不需要else
块。如果您收到多个参数,您也不必失败。你只需要失败,如果你不得到一场争论,然后你可以忽略其他一切,或者如果你至少没有得到一个争论就退出。
set -- "${1?ERR: Where\'s my argument?!?!}"
该声明做到了这一切。这样做的效果相同,但如果第一个参数仅为 nullstring 也会失败''
:
set -- "${1:?ERR: Where\'s my argument?!?!}"
当然,如果重点是从交互式 shell 调用 shell 函数,这也可能会杀死交互式 shell,因此您可以这样做:
(: "${1:?Where\'s my argument?}") || return && set -- "$1"
...这也能处理这个问题。但是,在我看来,除非绝对必要,否则 shell 函数永远不应该影响交互式 shell - 例如,如果它需要更改当前的 shell 变量或其他内容。因此,比上面的更好的方法是将函数声明为子 shell,例如:
fn() (set -- "${1:?Where\'s my argument?}" && echo "$1")
...做。
另一种方法是接受所有参数并将它们连接起来 - 因此所有参数在每种情况下都只被视为一个。你可以这样做:
fn() (
: "${1:?ERR: Where\'s my argument?}"
set -- "$*" && echo "$1"
)
fn '' ; fn here are a lot of arguments that will all be treated as one
###OUTPUT###
sh: line 2: 1: ERR: Where's my argument?
here are a lot of arguments that will all be treated as one
我个人不太喜欢sh: line 2: 1:
通常发生的情况——至少在交互式 shell 中是这样。我通常会CTRL+V CTRL+M
在前面加上一个ERR:
,这样它就会返回到终端中的行首并覆盖该位,但仍然将更有用的信息输出到日志中。喜欢:
fn() (
: "${1:?^MERR: Where\'s my argument?}"
set -- "$*" && echo "$1"
)
fn ; fn 2>&1 | cat -A
###OUTPUT###
ERR: Where's my argument?
sh: line 2: 1: ^MERR: Where's my argument?$