在 中bashrc
,我有一个警报函数,它可以采用 3 个变量:
a () {
local $1="${1:-3600}"
local $2="${2:-paa}"
local $3="${3:-alarm}"
sleep "$1" && $2 && $3
}
alias pah='pactl set-card-profile 0 output:hdmi-stereo'
alias paa='pactl set-card-profile 0 output:analog-stereo'
alias alarm='vlc ~/alarm.mp3'
在命令行上,以下命令可以很好地执行我的别名。
sleep 3600 && paa && alarm
但是,当我尝试制作上面显示的函数的这一部分时,我收到此错误:
bash: pah: command not found
另外:1 美元、2 美元、3 美元变量应默认为3600,帕阿, 和警报。
我也很困惑如何使用 $3 输入调用此函数,同时允许默认 $1 和 $2。
IE
a null null alarm2
转发说明:我在 Stack Overflow 上发布了这个问题,但意识到这个问题可能属于 Unix & Linux 堆栈交换。
答案1
我不明白你如何从运行中获得此输出a
:你是否发布了不同版本的输出?但无论如何我确实看到了代码有什么问题。
第一个问题是它local $1=…
并没有按照你的想法去做。它设置一个名称为第一个参数的变量,但不设置第一个参数。例如,如果将函数调用为a foo
,则第一行将局部变量设置foo
为值foo
。如果你a
不带任何参数调用,你会得到
bash: local: `=3600': not a valid identifier
(以及更多错误)因为 的 左边=
是一个空字符串,并且该空字符串不是变量的有效名称。
您不能使用赋值语法来设置编号参数:local 1=…
也不起作用。您需要为变量命名或使用set
内置函数一次性设置所有编号参数。
a () {
local delay="${1:-3600}"
local first_command_to_split_and_glob="${2:-paa}"
local second_command_to_split_and_glob="${3:-alarm}"
sleep "$delay" && $first_command_to_split_and_glob && $second_command_to_split_and_glob
}
第二个问题是别名只有在明确出现在命令开头时才会展开。它们不是从其他一些扩展的结果(例如获取变量的值)扩展而来的。
call 还有一个问题$first_command_to_split_and_glob
,那就是它只适用于简单的情况。它在空白处分割变量的值(即传递给函数的参数),然后将每一部分解释为通配符模式,如果该模式至少匹配一个文件名,则它会扩展该通配符模式。例如,尝试显示名为、和的a 2 'cat "file name with spaces"'
文件的内容。引号外的变量扩展应用“split+glob”操作:它既不产生变量的值也不对该值执行评估,而是中间的东西很少有用。看"file
name
with
spaces"
为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?更多细节。
要解决这两个问题,请使用eval
on 字符串。请注意"$first_command"
和周围的双引号,"$second_command"
以避免 split+glob。
a () {
local delay="${1:-3600}"
local first_command="${2:-paa}"
local second_command="${3:-alarm}"
sleep "$delay" && eval "$first_command" && eval "$second_command"
}
最后,要传递空参数,请使用引号分隔空字符串。例如:
a '' pah
等待 3600 秒,然后运行pah
,然后运行alarm
。