Bash:如何等待命令完成运行以解析出一个字符串?

时间:2017-05-23 20:57:41

标签: bash

我正在编写一个bash脚本,需要让npm run server完成运行,这将输出我需要的ID号

npm run server输出

running server...
....
...
...
Server version is /id/1345

我需要在命令完成运行后解析1345

我尝试过以下但没有成功:

idd=$(npm run server "$domain" &> >(sed -E -e 's:(^.*)(id/)(.*$):\3:g'))
echo $idd

抛出:

run.sh: command substitution: line 27: syntax error near unexpected token `>'

我也尝试过:

bundle_counter=$(npm run server "$domain" | sed -E -e 's:(^.*)(/b/)(.*$):\3:g')

失败了。

3 个答案:

答案 0 :(得分:2)

idd=$(npm run server "$domain" | sed -n -E '$s+id/(.*)$+\1+p')

我将npm的输出输出到sed,就像你在第二个片段中所做的那样。您也使用的-E标志可以启用扩展的正则表达式。我现在甚至不需要这些,但我认为它是标准的,因为ERE更有用。

-n告诉sed默认情况下不会在转到下一行时打印其缓冲区。它与在所有其他命令之后在每个输入行上使用d时大致相同。使用-n时,您必须明确要求sed使用p命令打印某些行 - 但这实际上并未在此处使用,因为我们很快就会看到!

$将确保该命令仅在输入的最后一行执行。

s命令是替换命令。你可以在它之后使用任何字符,这将是s的分隔符。经典是/,但在这里我使用+,因为我们在针中使用/,这样我们就不必逃避{{1} }}。 /是针,id/(.*)$是替代品。你没有必要像你一样锚定你的字符串,所以\1和相应的替换^(.*)id/(.*)$的针是等价的但是多余的(并且很可能会产生轻微的性能开销)。

因为在\2之后没有分号,s实际上不是这里的单独命令,而是p的标志。如果s命令成功找到要替换的内容,它将打印缓冲区。

答案 1 :(得分:2)

idd=$(npm run server "$domain" 2>&1 | sed -E -ne 's:(^.*)(id/)(.*$):\3:p')
  • 2>&1将stderr合并到stdout。
  • 将输出传递给sed的简单管道。
  • sed命令中的
  • -n不打印任何不匹配的行。
  • 在正则表达式末尾的
  • p打印匹配。

答案 2 :(得分:1)

直接问题

错误消息表明您正在调用Bash为sh (或至少在POSIX兼容模式下),在这种情况下进程替换({{ 1}}和<(...))不受支持,因为他们不属于POSIX

如果您的>(...)命令原则上有效,那么确保您的命令由sed运行 - 通过该名称调用 就足够了,使用shebang line bash

也就是说,使用输出过程替换是不必要的复杂。

#!/bin/bash命令的问题:

您的sed命令无法按预期工作,因为在没有选项sed的情况下,-n仍会打印所有(可能已修改) )输入线,而不仅仅是(修改过的)感兴趣的线 因此,sed(替换)命令的正则表达式匹配的任何行仍然是仍然打印,按原样

有关可行的解决方案,请参阅Ewan Mellor's helpful answer