子shell的$$

下面是一段代码,我偶然发现有点问题。

#!/bin/bash

TestID()
{
        echo "in function : $$"
}

TestID &
echo "\$! : $! "

echo "\$\$ : $$ "
sleep 1

[firefox@fire ShellPractice]$ ./stopped.sh
$! : 15021
$$ : 15020
in function : 15020

疑问就是在这里,$!代表是最后一个后台程序的ID$$当前进程ID,而&出来的应该是一个子shell但是它的ID(在子shell里这时候是$$打印出来的)和父shell是“一样”的。我去论坛上问了下,然后查了些资料。下面是一些简单的介绍:


shell什么情况下会产生子进程

1:&,提交后台作业

If a command is terminated by the control operator `&’, the shell executes the command asynchronously in a subshell.

2:管道

Each command in a pipeline is executed in its own subshell

3:括号命令列表

()操作符

Placing a list of commands between parentheses causes a subshell environment to be created

4:执行外部脚本、程序:

When Bash finds such a file while searching the `$PATH’ for a command, it spawns a subshell to execute it.  In other words, executing  filename ARGUMENTS is equivalent to executing bash filename ARGUMENTS

再看看 man bash 里面对于$的解释

“$”  Expands to the process ID of the shell. In a () subshell, it  expands to the process ID of the current shellnot the sub‐shell.

那么这里的current shell怎么解释呢?字面意思是“当前的shell”。这里有有一篇博客讲子shell,我觉得讲的很好 http://blog.youkuaiyun.com/sosodream/article/details/5683515 。用 ./xxx.sh 执行脚本的时候也会生成子shell,原来的shell会有一个 ID,这里假设叫ID1,然后进入脚本,这时脚本里的$$就是current shell的ID(由ID1生出的子shell的ID)之后再生出其余的子shell的$$都是current shell的ID,也就是由ID1生出来的ID,注意:子shell的ID可不是$$。子shell有它自己的ID。至于怎么获取,一般都用$!来获取。

再来看看下面的脚本

#!/bin/bash

echo "\$\$ outside of subshell = $$"
echo "\$BASH_SUBSHELL outside of subshell = $BASH_SUBSHELL"
echo "\$BASHPID outside of subshell = $BASHPID"
echo "-------------------"
(
        echo "\$\$ inside of subshell = $$"
        echo "\$BASH_SUBSHELL inside of subshell = $BASH_SUBSHELL"
        echo "\$BASHPID inside of subshell = $BASHPID"
)
echo "-------------------"

$BASHPID就是指当前shell。

现在再来看看 man bash 中“$”的解释

[root@fire ShellPractice]# echo $$
2618

如果你在子shell里面执行这条命令,其实是$$先替换为2618,然后再进行echo,$$一直都指的的是current shell。


<think>好的,我现在需要帮助用户了解Shell中特殊参数$@的用法。首先,我应该回顾用户提供的引用内容,尤其是引用[1]和引用[3],因为它们提到了相关的参数变量。用户的问题集中在$@的用法上,所以需要详细解释它的作用和与其他参数比如$*的区别。 根据引用[1],$@用于获取所有传给脚本的参数,不加引号时和$*相同,但加双引号时不同。当使用"$@"时,每个参数都被视为独立的字符串,保留空格,而"$*"则合并成一个字符串。这个区别在传递参数给其他程序时很重要,特别是当参数中有空格的时候。 接下来,我需要结合实例来说明。比如,在脚本中使用"$@"可以确保每个参数正确传递,避免因为空格导致的问题。比如用户提供的引用[3]中的例,执行sh parm.sh a b,这里参数a和b被正确处理,但如果有带空格的参数,比如"a b" c,这时使用"$@"就能正确分割成两个参数,而$*可能不会。 另外,用户可能还不太清楚如何在实际脚本中应用$@。比如在函数中使用它来传递所有参数,或者在循环中逐个处理参数。可能需要举一个函数的例,像引用[2]中的diskusage函数那样,展示如何用$@来处理参数。 还需要注意,当不带引号时,$@和$*的行为是一样的,但带引号时有区别。这点需要强调,因为这是容易出错的地方。例如,在for循环中遍历参数时,使用带引号的"$@"可以正确处理每个参数。 最后,总结$@的最佳实践,比如在需要保留参数中的空格时使用带引号的"$@",并与其他参数变量比较,帮助用户理解不同场景下的选择。同时,生成相关问题,帮助用户进一步学习其他参数如$*和$#的用法。</think>关于Shell中特殊参数`$@`的用法解析如下: ### 一、`$@`的核心作用 `$@`是Shell中的特殊参数,表示传递给脚本或函数的所有位置参数集合。其核心特性是**在双引号中能保留每个参数的独立性**,尤其适用于处理含空格的参数[^1]。 ### 二、关键用法及示例 1. **基础参数传递** ```bash #!/bin/bash echo "参数列表:" for arg in "$@"; do echo "参数: $arg" done ``` 执行命令 `./test.sh "file 1.txt" "file 2.log"` 时: - 输出两个独立参数:`file 1.txt` 和 `file 2.log` 2. **函数参数转发** ```bash copy_files() { cp -v "$@" /backup/ } ``` 调用 `copy_files "report 2023.pdf" data.csv` 时: - 能正确传递含空格的参数 `report 2023.pdf` 3. **与`$*`的关键区别** | 场景 | `"$@"` | `"$*"` | |--------------|--------------------------|--------------------------| | 参数数量 | 保留原始参数个数 | 合并为单个字符串 | | 空格处理 | 保留参数内的空格 | 空格被解释为参数分隔符 | | 典型用途 | 需要保留参数边界时 | 需要合并参数时 | ### 三、最佳实践建议 1. 在循环中始终使用 `for arg in "$@"`(可简写为 `for arg`) 2. 调用命令时优先使用 `command "$@"` 格式 3. 避免与未加引号的 `$@` 混用,防止意外分词
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值