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.
相关推荐
在这项工作中,利用函数$$ f(R)= R + \ alpha R ^ n $$ f(R)= R +αRn研究f(R)重力中的可穿越虫洞,其中$$ \ alpha $$α n是任意常数。 Samanta等人提出的形状函数$$ b(r)= \ frac {r} {\ exp(r-r_0)} $$ ...
### 1. **移动光标与编辑行** - **$Ctrl+a**:将光标移动到当前行的最开始位置。 - **$Ctrl+e**:将光标移动到当前行的最末尾。 - **$Ctrl+u**:清除光标前的所有字符,如果光标位于行尾,则清除整行。 - **$Ctrl+l...
1) as varchar) + ' ' + @OrderField + ' from ' + @TableName + ' ' + @Condition + ' order by ' + @OrderField + ' desc) temp) order by ' + @OrderField + ' desc' end end end else begin if @...
1. **$0**: 这个变量保存了当前执行的Shell脚本的文件名。例如,如果你的脚本名为`test.sh`,在脚本内部`$0`就会打印出`test.sh`。 2. **$#**: `$#`表示传递给脚本或函数的参数数量。在上述示例中,如果运行`./test...
通过Ξcc + + $$ {\ Xi} _ {cc} ^ {++} $$搜索Ξcc + + $$ {\ Xi} _ {cc} ^ {++} $$重子 D + pK-π+衰减是通过与LHCb实验在13 TeV质心能量下pp碰撞中通过LHCb实验记录的1.7 fb -1的综合光度对应的数据样本执行的。...
我们的分析基于欧洲扭曲质量合作组织产生的半轻体形式因子的结果,在整个值范围内,$$ N_f = 2 +1 + 1 $$ Nf = 2 + 1 + 1种动态夸克。 实验中可访问的平方4动量传递。 适当考虑了晶格数据与实验数据中存在的统计和...
1. **理论控制的重要性**:对标准模型背景的良好理论控制是正确解释可能在该通道中出现的新物理信号的前提条件。这意味着,在制定任何实际的新物理探测策略之前,需要仔细重新检查在更排他的选择条件下这些可观测量...
利用Yang-Mills场,分层剪切流初始状态和高分辨率($$ 3 + 1 $$ 3 + 1)D单元格相对论(PICR)流体力学模型,我们计算了$$ \ varLambda $$Λ RHIC能量为$$ \ sqrt {S_ {NN}} = 200 $$ SNN = 200 GeV时外围Au + Au...
例如,C1 单元格有公式:=$A$1+$B$1,当将公式复制到 C2 单元格时仍为:=$A$1+$B$1,当将公式复制到 D1 单元格时仍为:=$A$1+$B$1。 绝对引用可以锁定单元格的地址,使得公式在复制时不会改变其引用单元格。例如,...
$end = $start + (int)$res['users'][$m]['list_num'] - 1; $objPHPExcel->getActiveSheet()->mergeCells('B'.$start.':B'.$end); $objPHPExcel->getActiveSheet()->mergeCells('C'.$start.':C'.$end); ...
示例1:复制代码 代码如下:<?phpfor($q=1;$q<=9;$q++){ for($w=0;$w<=9;$w++){ for($e=0;$e<=9;$e++){ if($q*$q*$q + $w*$w*$w + $e*$e*$e == 100*$q + 10*$w + $e){ echo “$q $w $e “.””; }...
- `pid=`ps ax | grep '/home/tomcat5' | head -1 | awk '{print $1}'`;`: 查找运行在`/home/tomcat5`目录下的Tomcat进程PID。 - `echo "the tomcat pid=$pid" >> $log;`: 记录Tomcat进程的PID到日志文件。 - `max=...
特别地,我们将(0,0)标识为黎曼流形,(1,0)标识为非相对论时空,(1,1)标识为Gomis–Ooguri非相对论字符串,$$(D {-1},0) $$(D-1,0)作为超相对论的Carroll几何,(D,0)作为Siegel的手性弦。...
该分析使用来自质子-质子碰撞的数据,其综合亮度为35.9 $$ \\ text {fb} ^ {-1} $$ fb-1 at $$ \ sqrt {s} = 13 \,\ text {TeV } $$ s = 13TeV,是由LHC的CMS检测器收集的。 假设$$$ \ mathrm {J} / \,观察到的$$...
- **解析**:已知$x = 1$是方程$x^2 + ax + 2b = 0$的一个根,代入得到$1 + a + 2b = 0$,从而有$a + 2b = -1$。题目要求求$2a + 4b$的值,通过观察可以发现这是$a + 2b$的2倍,因此答案为$-2$。 5. **利用一元二...
2. 动态规划状态转移:对于dp数组中的其他位置(i, j),其值等于网格值加上左侧位置dp[i][j-1]和上方位置dp[i-1][j]中的较小者。这是因为要达到当前位置(i, j),我们可以从左边或上方的网格过来,选择路径和较小的...
$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'; // ...
例如,公式“=$A$1+B1”在B2处复制后仍为“=$A$1+B2”,确保始终从A1单元格获取数据。 混合引用结合了相对和绝对引用的特点,可以锁定行或列,但允许另一方向变化。例如,“$A1”会锁定列A,而在行方向上使用相对...
在本文中,我们通过颜色-来对$$ Z \ rightarrow \ Upsilon(1S)+ g + g $$ Z→Υ(1S)+ g + g进行前导(NLO)研究。 单重态(CS)$$ b {\ bar {b}} $$bb¯状态。 我们发现,新计算的NLO QCD校正对此过程可能会显着...