What does ${1+"$@"} mean
...and where is it necessary?
2012-06-16 (see recent changes)
It's a workaround for older releases of the traditional Bourne shell: they parse "$@" in an unexpected way if no arguments were supplied.
All traditional Bourne shells since the SVR3 release and all modern bourne compatible shells behave intuitively.
One might argue, whether the old behaviour is a bug in the very sense, or unintuitive de-facto behaviour. But it was not properly specified, yet, and definitely error-prone.
(It's also a workaround for a problem in various shells if you want to use set -u. See more at the bottom of this page, "Oh wait, ...")
Example
in a shell, where this workaround is necessary.
With the following script,
$ cat args.sh
for i in "$@"; do
echo arg: \"$i\"
done
you get output as expected if you provide at least one argument:
$ sh args.sh 1 2
arg: "1"
arg: "2"
However, without arguments, you still get (empty) output, instead of no output at all:
$ sh args.sh
arg: ""
Why is this relevant?
Keep in mind, that "$@" is most frequently used for passing on arguments, or for iterating over them in a loop, like above.
Thus a mechanism for collapsing the argument list to nothing--and not to the empty argument--is needed.
How does it work?
The ${1+"$@"} syntax first tests if $1 is set, that is, if there is an argument at all.
If so, then this expression is replaced with the whole "$@" argument list.
If not, then it collapses to nothing instead of an empty argument.
Why does it work this way?
The problem only arises if a variable is quoted, and $1 is not.
The workaround is not limited to this variant. These work also: ${@+"$@"} and ${*+"$@"},
but the abovementioned variant is the widely known one.
Another, historic problem
Even with the above workaround, early shells before SVR2 (7th edition, BSDs, SysIII and SVR1) discard empty arguments in the argument list.
$ sh ./args.sh 1 '' 2
arg: "1"
arg: "2"
This looks quite similar at first, but in practice it's less relevant, because dealing without any argument is much more likely to happen.
Portability
${1+"$@"} is reliable and portable -- with one exception:
zsh until release 4.3.0, in sh emulation mode (which means the option shwordsplit is set), does word splitting on the resulting arguments.
$ sh ./args.sh '1 2'
arg: "1"
arg: "2"
An alternative
You might just loop yourself over the arguments:
for i
do
echo "$i"
done
interestingly also valid if merged but without semicolon:
for i do
echo "$i"
done
Although these are not documented for the Version 7 Bourne shell (and its variants on early BSDs), they work on these systems, too.
(Picked up from the german lang usenet posting <3BE2D2D3.I715123W@bigfoot.de> from Gunnar Ritter; and I could confirm this on all the flavours).
See more details about this short form of the for-loop at the end of this page.
In contrast to ${1+"$@"}, these variants even work correctly in the pre-SVR2 variants if there are empty arguments in the list (pointed out by Stéphane Chazelas and I can confirm it).
However, for passing on the arguments to another program (instead of iterating over them) ${1+"$@"} (or "$@") is certainly the only solution.
Which Bourne shells exactly need the workaround?
These shells behave the old way and need ${1+"$@"}:
Certainly: /bin/sh on 7th edition (aka Version 7). And thus also /bin/sh on original BSDs, until these shipped the Almquist shell (after 4.3BSD-Reno)
HP-UX 8, 9 /bin/sh, HP-UX 10.x, 11.x /usr/old/bin/sh (as /bin/sh has become a ksh)
OSF1/V4 and V5 aka Tru64 /bin/sh
Ultrix /bin/sh and /bin/sh5
Sinix 5.20 /bin/sh in both the "ucb" and the "sie" universe
In contrast, these Bourne shell variants behave the modern way:
8th edition (aka Version
/bin/sh
SunOS 4.1.x and SunOS 5.x /bin/sh
IRIX 5 - IRIX 6.3 /bin/sh, IRIX 6.4+x /usr/bin/bsh (as /usr/bin/sh has become a ksh)
AIX 3.2.4 /bin/sh, AIX 4.x /usr/bin/bsh (as /usr/bin/sh has become a ksh)
OpenServer 3 ff. /usr/bin/sh
MUNIX 3.1 (Cadmus, SVR3.1) /bin/sh
Sinix 5.20 /bin/sh in the "xopen" universe
Oh wait, there's another meaning
It's also a workaround for a problem in some shells if you want to use the flag u ("error upon using empty variables")
and "$@" (or $@, "$*", $*) is used without arguments. Example:
$ shell -cu 'echo "$@"; echo not reached'
@: parameter not set
$ shell -cu 'echo ${1+"$@"}; echo ok'
ok
These shells for example need that workaround:
bash-4.0.0 ... -4.0.27
Bourne shells (traditional)
dash-0.4.6 ... -0.4.18
ksh88
ksh93 until release t+20090501
mksh (as pdksh descendant)
NetBSD 2 ff. /bin/sh
pdksh-5.1.3, -5.2.14
posh < 0.10 (as pdksh descendant)
Endnote
Details about the short form of the for-loop.
Among the four variations
$ for i
do
$ for i do
$ for i; do
$ for i;
do
The original 7th ed Bourne shell and all its later flavours don't accept the third and fourth variant [1].
Interestingly, the second variant is accepted (which isn't consistent with accepting the first, but consistent with not accepting the third).
ksh86, ksh88a ff. and ksh93(d..u) accept all but the fourth variant.
The reason might be that the code is partly based on the Bourne shell.
The original Almquist shell (ash) accepts all but the second variant.
It just handles the terminator sort of consistently.
The almquist shells since 4.4BSD and 386BSD (and thus all descendants except Minix pre-3.1.3)
accept all four variants, apparently fixed for backwards portability or flexibility.
All other shells I tried accept all four variants (apparently intentionally being backwards portable or flexible, too),
bash-1.05 ff., pdksh-5.2.14 (thus mksh, posh.), zsh-3.0 ff.
The third variant is not POSIX conformant.
Update: Jens Schweikhardt reported it as issue, and Jilles Tjoelker mentioned the fourth variant, which I added here.
[1] This is weird because ; (semicolon) and newline are usually equivalent.
The documentation doesn't explicitly tell if a terminator is required/allowed; it seems to read as if it's not allowed
for name [in word ...] do list done
Each time a for command is executed name is set to the
next word in the for word list If in word ... is omit-
ted then in "$@" is assumed. Execution ends when there
are no more words in the list.
Comparison with the while control command suggests itself, but is not helpful. The while description doesn't match behaviour, because the terminator in list is not optional
(and because it's incorrect anyway, because "do list" is not optional as written, which will be fixed in the System III documentation),
while list [do list] done
A list is a sequence of one or more pipelines separated by
;, &, && or || and optionally terminated by ; or &. [...]
Newlines may appear in a list, instead of semi-
colons, to delimit commands.
相关推荐
特别地,我们假设在($$ 2 + 1 $$ 2 + 1)维度中没有宇宙学常数的爱因斯坦-功率-麦克斯韦理论,假设重力和电磁耦合均与尺度相关,我们将详细研究尺度如何 依赖的场景会影响任何功率参数值的经典黑洞的视界和热力学...
通过Ξcc + + $$ {\ Xi} _ {cc} ^ {++} $$搜索Ξcc + + $$ {\ Xi} _ {cc} ^ {++} $$重子 D + pK-π+衰减是通过与LHCb实验在13 TeV质心能量下pp碰撞中通过LHCb实验记录的1.7 fb -1的综合光度对应的数据样本执行的。...
function utf_substr($str,$len){ ... $temp_str=substr($str,0,1); if(ord($temp_str) > 127){ $i++; if($i<$len){ $new_str[]=substr($str,0,3); $str=substr($str,3); } }else{
我们将轴向矢量介子$$ K_1(1270)$$ K1(1270)和$$ K_1(1400)$$ K1(1400)视为两个$$ | ^ 3P_1 \ rangle $$ |3P1⟩和 $$ | ^ 1P_1 \ rangle $$ |1P1⟩的混合角$$ \ theta $$θ等于$$(-34 \ pm 13)^ \ circ $$...
特殊变量列表 变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。...命令行参数用 $n 表示,例如,$1 表示第一个参
1. **基本步骤** - 比较相邻的元素,如果第一个比第二个大,就交换他们两个。 - 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 - 针对所有的元素重复以上...
5. **负浮点数**:“`^-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$`” - 解释:仅匹配负浮点数。 6. **字母串**:“`^[A-Za-z]+$`”,“`^[A-Z]+$`”,“`^[a-z]+$`” - ...
$counter += 1; ``` 在循环结构中,计数器特别有用。例如,`for`循环就是一个常用于计数的场景: ```php for ($i = 0; $i ; $i++) { echo "这是第 " . $i . " 次迭代\n"; } ``` 在这个例子中,`$i`就是计数器,...
$n[$lo + 1] = $n[$hi - 1]; $n[$hi - 1] = $t; $lo++; $hi--; } } $n[$left] = $n[$lo]; $n[$lo] = $pivot; return $lo; } function quicksort(&$n, $left, $right) { global $n; if ($left $right) { ...
输入的第1行是一个整数T,表示测试数据的个数(1)。接下来有T组测试数据。各组测试数据的第1行是一个整数T,表示第i组数据中串的个数。各组测试数据的第2到N+1行,每行一个串,串中不会有空格,但行首和行末可能有...
$directions = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; // 上下左右四个方向 $count = 0; for ($i = 0; $i $m; $i++) { for ($j = 0; $j $n; $j++) { if ($grid[$i][$j] === '1') { $grid[$i][$j] = '0'; // ...
更重要的是,我们预测2P $$ \ Lambda _ {c} ^ + $$Λc+状态的质量反比关系,即$$ \ Lambda _c(2P,1/2 ^-)$$Λc (2P,1 / 2-)状态高于$$ \ Lambda _c(2P,3/2 ^-)$$Λc(2P,3 / 2-),这与常规淬火夸克...
3. 开始外层循环,共进行`$length - 1`轮,因为每次遍历都能确定一个最大(或最小)值。 4. 在每轮中,进行内层循环,从第一个元素开始到倒数第二个元素(`$length - 1`)。 5. 在内层循环中,比较相邻两个元素,...
通过分析提供的压缩包文件(如`calendarix_1_8_20081228_trial`),我们可以深入了解这个日历的具体实现和可能的扩展功能。 总之,PHP的简单日历实现涉及日期处理、二维数组操作以及HTML和CSS的生成。这个项目为...
这两种操作虽然表面上看起来都是将变量的值增加1,但实际上它们的执行顺序和结果存在细微的差别,理解这些差异对编写正确的代码至关重要。 首先,我们来看前置自增运算符(++$i)的用法。当使用++$i时,PHP解释器会...
1. 截取GB2312中文字符串 <?php < ?php //截取中文字符串 function mysubstr($str, $start, $len) { $tmpstr = ; $strlen = $start + $len; for($i = 0; $i < $strlen; $i++) { if(ord(substr($str, $...
1. 有助于避免管理层为了短期利润最大化而过度生产,因为固定成本会被分摊到库存中。 2. 强调可控制的成本,鼓励管理层关注能直接影响利润的变动成本。 吸收成本法的局限性: 1. 利润可能会因管理层对库存的操纵而...
1.关于this.$refs的使用场景 如果ref属性加在普通元素上,那么this.$refs.name则指向该DOM元素 ”p”>hello <!– this.$refs.p 指向该DOM元素 –> 如果ref属性加在组件上,那么this.$refs.name指向该组件实例 ...
//1、冒泡排序 function bubble_sort($arr){ $n = count($arr); for($i=0;$i<$n-1;$i++){ for($j=$i+1;;$j<$n-$i;$j++){ if($arr[$j]<$arr[$i]){ $temp = $arr[$i]; $arr[$i] = $arr[$j]; ...