Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash:将结果赋给变量时换行计数不同_Bash_Shell_Scripting - Fatal编程技术网

bash:将结果赋给变量时换行计数不同

bash:将结果赋给变量时换行计数不同,bash,shell,scripting,Bash,Shell,Scripting,假设我想看看一个程序已经运行了多少个副本。我可以这样做: ps ax | grep -c "$0" 该命令本身会产生预期的结果。但是,如果我尝试将输出分配给一个变量,它将递增1!无论我如何尝试: var=$(ps ax | grep "$0" | sed -n '$=') var=`ps ax | grep -c "$0"` 有人能告诉我捕获正确输出的正确方法吗 如果能知道为什么会发生这种情况,那也太好了 更新 在@fedorqui的第一次回复后,我意识到我还不够清楚。让我详细说明: 我在同

假设我想看看一个程序已经运行了多少个副本。我可以这样做:

ps ax | grep -c "$0"
该命令本身会产生预期的结果。但是,如果我尝试将输出分配给一个变量,它将递增1!无论我如何尝试:

var=$(ps ax | grep "$0" | sed -n '$=')
var=`ps ax | grep -c "$0"`
有人能告诉我捕获正确输出的正确方法吗

如果能知道为什么会发生这种情况,那也太好了

更新 在@fedorqui的第一次回复后,我意识到我还不够清楚。让我详细说明:

我在同一个bash脚本中运行上述三个命令。当我运行第一个程序时,它打印出数字2:程序本身和grep进程,并将该程序作为参数。当我在变量赋值中运行这些相同的命令时,会存储数字3

请注意,我使用两种不同的方法计算行数,grep和sed。在这两种情况下,它们都返回3,而不是正确答案2

下面是一个要在test.sh文件中尝试的合并示例:

echo -n "without assignment: "
ps ax | grep -c "$0"
var=$(ps ax | grep "$0" | sed -n '$=')
echo "using sed method: $var"
var=`ps ax | grep -c "$0"`
echo "using grep method: $var"
我的debian box上的结果:

without assignment: 2
using sed method: 3
using grep method: 3
再次提出问题:为什么会发生这种情况,以及如何预防或解决

因为
grep
进程本身由
ps
返回

您可以选择以下任一选项:

“欺骗”
grep
通过包围其中一个搜索使其自身不匹配 字符类
[]
中的字符,它不会更改 功能:

或者,在这种情况下

管道连接到
grep-v grep
,使流程不匹配:

var=$(ps ax | grep -v grep | grep "$0")

请看一个例子。这里我们有一个进程
sleep

$ sleep 20 &
[1] 5602
如果我们在
ps
的输出中检查它,它会出现两次

$ ps -ef| grep sleep
me   5602  5433  0 09:49 pts/2    00:00:00 sleep 20
me   5607  5433  0 09:49 pts/2    00:00:00 grep --colour=auto sleep
因此,我们可以使用字符类:

$ ps -ef| grep [s]leep
me   5602  5433  0 09:49 pts/2    00:00:00 sleep 20
或grep退出grep流程:

$ ps -ef| grep sleep | grep -v grep
me   5602  5433  0 09:49 pts/2    00:00:00 sleep 20
  • 命令替换本身在子shell中运行,因此这是一个
    bash
    进程

  • 您对
    bash
    $0
    )的搜索,即
    grep-cbash
    也会在当时的进程表中结束,因此这是另一个包含字符串
    bash
    的进程(
    grep
    )。请注意,这可能不会在运行时显示在进程表中,具体取决于系统的繁忙程度

  • 您有两个(或任意两个)实际运行的
    bash
    进程(会话)可能是其余的

您可以使用正则表达式技巧消除误报,即从计数中删除一个:

ps ax | grep -c "[b]ash"
在执行命令替换时,它仍然会计算子shell:

var=$(ps ax | grep -c "[b]ash")
因此,您需要手动从该计数中删除一个

示例:

$ var=$(ps ax | grep -c "bash")    
$ echo $var
4

$ var=$(ps ax | grep -c "[b]ash")   
$ echo $var
3

您的命令也计算grep命令行

ps ax | grep -v grep | grep -c "$0"

应该从计数中省略grep

如果$0是
grep
;-)我真的很欣赏这个全面的答案,但这不是解决办法。我在同一个bash脚本中运行所有3行。当我运行第一个程序时,它会输出2:正如你所说的程序本身和grep进程,并将该程序作为参数。当我将这些命令作为变量赋值运行时,数字3被存储。@blackSmith说得对!尽管我不认为这种情况会发生很多次,但由于
grep
将只运行一小会儿,而不是我们通常使用
ps
@EricJensen检查的长时间运行的进程,这是非常奇怪的。我用
sleep 200&
检查了这个问题,并用代码检查
sleep
而不是
$0
,它总是返回2。介意提供更多细节吗?@fedorqui我刚刚更新了问题您是说使用var=''或var=$()运行另一个bash shell?因此,如果命令在脚本中运行,那么此时将有两个命令在运行?这可能是答案,但是我仍然需要一个搜索脚本本身运行实例的解决方案。还有比搜索0美元更好的主意吗?每次程序运行时,都需要确保上一个实例没有继续运行。@EricJensen在
$(foobar)
中,命令
foobar
在子shell中运行。。您可以通过
$$
找到当前进程的PID,例如您的脚本。。另外,由于您的脚本将作为
bash
的参数运行,您可能应该搜索脚本名称并与PPID和
$$
组合以获得所需内容。对我来说,使用
/script.sh
运行脚本可以解决问题。如果我使用
bash script.sh
运行,它会得到一个额外的进程。另外,我想知道:为什么您想知道您的脚本有多少个实例正在运行?如果要避免并发,还有其他更安全的方法。例如,在启动时创建一个虚拟目录,以便另一个看到它的实例将确定脚本正在运行。完成后,删除dir。@fedorqui基本上就是锁文件的概念,对吗?也许我应该走那条路。我想看一些关于锁文件和过程监控的阅读材料。。。不是为了这个项目,只是为了general@triplee注意这不是重复的,请检查问题末尾给出的样本。问题在于,
ps-ef | grep$0
返回的进程比
var=$(ps-ef | grep$0)
少一个进程。在中有一个非常有趣的线程。我认为创建一个dir,作为一个原子操作,是最好的方法,但是在那里我看到了许多其他(也许更好)的解决方案。