【问题标题】:How to make $! to work inside `sh -c "$!"` [duplicate]如何赚美元!在`sh -c“$!”`中工作[重复]
【发布时间】:2018-01-02 13:39:42
【问题描述】:

请帮忙看看是否有办法使下面的脚本可行?

name='bob'
# below script reports 'bash: !: event not found' error
sh -c "echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"" 
# below script $name will not become bob
sh -c 'echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"' 

[添加 01/03]

这个问题与this one有些重复,是我的错,原问题的描述不够清晰准确,我尝试创建一个新的,使其更具体和清晰。

【问题讨论】:

  • 试试sh -c 'echo '"$name"'; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"'
  • @hek2mgl 然后$name 不会被扩展(除非你单独export 它)。
  • Like I already told you, 使用 set +H 来防止 Bash 产生 event not found 错误。
  • @Cyrus 但是sh 没有这个问题。 Csh 风格的历史扩展 (mis) 功能是 Bash 扩展。
  • @tripleee:谢谢,我回滚了我的编辑。

标签: bash shell


【解决方案1】:

似乎正在尝试解决event not found 问题。

当您在 Bash 中有 set -H 并在交互式命令中使用感叹号(在单引号或反斜杠转义之外)时,就会发生这种情况。

我已经发布了an answer,我认为有六个 cmets 解释了正在发生的事情以及如何解决它。

set +H

此命令禁用在交互式会话中使用感叹号的 Bash 历史机制。

此外,在双引号内,您必须转义美元符号才能将其逐字传递给子shell。

sh -c "echo \"$name\"
    sleep 20 & pid1=\$!
    sleep 10 & pid2=\$!
    echo \"pid1: \$pid1, pid2: \$pid2\"" 

【讨论】:

  • 这不是一个正确的答案,但我希望至少这会提示您澄清这个确切的问题是否不是您仍在尝试解决的问题。否则请接受我提议的副本。
  • 恐怕我没有抓住你的意思,实际上我想将$!作为PID号存储到一个变量中并稍后使用它,event not found是我遇到的一个侧面错误对于我的脚本:sh -c "echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"",如果我使用set +H; sh -c "echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"",则没有event not found 错误,但$! 不会转换为我想要的PID 号。
  • 升级版答案。虽然这基本上是 stackoverflow.com/a/37746186/874188 的副本
【解决方案2】:

cmets 提议混合引号和禁用历史扩展,但更好的解决方案(IMO)是将名称作为参数传递:

sh -c 'echo "$1"; sleep 20 & pid1=$!; ...' sh "$name"

【讨论】:

  • 为什么是第二个sh?只是为了使参数为$1 而不是$0
  • @Melebius 是的。自定义规定 $0 应该是外壳的名称。这不是必需的,但这是最佳做法。
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多