bash:解析长命令末尾的数字

bash:解析长命令末尾的数字,bash,Bash,我正在编写一个shell脚本,它将运行一个命令并解析出最后几个数字(每次都会更改) 运行npm run server后要分析的文本,输出: Please visit http;//mysite.com/id/2318 我想解析出该值并将其分配给id: 2318 我的尝试: id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p') id=$(echo npm run server | sed -n 's:.*id\/\(.*\)

我正在编写一个shell脚本,它将运行一个命令并解析出最后几个数字(每次都会更改)

运行
npm run server
后要分析的文本,输出:

Please visit http;//mysite.com/id/2318
我想解析出该值并将其分配给
id

2318
我的尝试:

id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p')
id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p') 
没有返回任何内容。

我假设:

  • 您希望作为命令调用
    npm run server
  • 该命令在某个点在其stdout上发出给定消息(与stderr相反,直接发送到TTY等)
  • 此命令不在后台运行,并且您希望它即使在给出输出后也能继续运行
  • 启动它的shell脚本退出后,
    npm run server
    继续运行并不重要

如果所有这些假设都是正确的,考虑一个过程替代这项工作:

#!/usr/bin/env bash
regex='Please visit .*/([[:digit:]]+)$'    # define a regex to search for the string
exec 3< <(npm run server)                  # attach output from "npm run server" to FD 3

## the action is here: searching through output from server until we find a match
while read -r server_output <&3; do        # loop reading a line at a time from the server
  if [[ $server_output =~ $regex ]]; then  # if a line matches the regex...
    id=${BASH_REMATCH[1]}                  # then put the first capture group in a variable
    break                                  # and stop looping further.
  fi
done

## after-the-fact: log success/failure, and set up any future output to be consumed
## ...so the server doesn't hang trying to write later output/logs to stdout w/ no readers.
if [[ $id ]]; then                         # if that variable contains a non-empty value
  echo "Detected server instance $id" >&2  # log it...
  cat </dev/fd/3 >/dev/fd/2 & cat_fd=$!    # start a background process to copy any further
                                           # stdout from service to stderr...
  exec 3<&-                                # then close our own copy of the handle.
else
  echo "Unable to find an id in stdout of 'npm run server'" >&2
  exit 1
fi

## and we're done: if you like, run your other code here.

## also: if you want to wait until the server has exited
##       (or at least closed its stdout), consider:
[[ $cat_fd ]] && wait "$cat_fd"
#/usr/bin/env bash
regex='Please visit.*/([[:digit:]+)$'#定义一个正则表达式来搜索字符串
执行官3我假设:

  • 您希望作为命令调用
    npm run server
  • 该命令在某个点在其stdout上发出给定消息(与stderr相反,直接发送到TTY等)
  • 此命令不在后台运行,并且您希望它即使在给出输出后也能继续运行
  • 启动它的shell脚本退出后,
    npm run server
    继续运行并不重要

如果所有这些假设都是正确的,考虑一个过程替代这项工作:

#!/usr/bin/env bash
regex='Please visit .*/([[:digit:]]+)$'    # define a regex to search for the string
exec 3< <(npm run server)                  # attach output from "npm run server" to FD 3

## the action is here: searching through output from server until we find a match
while read -r server_output <&3; do        # loop reading a line at a time from the server
  if [[ $server_output =~ $regex ]]; then  # if a line matches the regex...
    id=${BASH_REMATCH[1]}                  # then put the first capture group in a variable
    break                                  # and stop looping further.
  fi
done

## after-the-fact: log success/failure, and set up any future output to be consumed
## ...so the server doesn't hang trying to write later output/logs to stdout w/ no readers.
if [[ $id ]]; then                         # if that variable contains a non-empty value
  echo "Detected server instance $id" >&2  # log it...
  cat </dev/fd/3 >/dev/fd/2 & cat_fd=$!    # start a background process to copy any further
                                           # stdout from service to stderr...
  exec 3<&-                                # then close our own copy of the handle.
else
  echo "Unable to find an id in stdout of 'npm run server'" >&2
  exit 1
fi

## and we're done: if you like, run your other code here.

## also: if you want to wait until the server has exited
##       (or at least closed its stdout), consider:
[[ $cat_fd ]] && wait "$cat_fd"
#/usr/bin/env bash
regex='Please visit.*/([[:digit:]+)$'#定义一个正则表达式来搜索字符串
exec 3<解决您原来的一行代码:
我的尝试:

id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p')
id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p') 
没什么 正在归还

您可以尝试以下方法:

id=$(npm run server | sed -E -e 's:(^.*)(id/)(.*$):\3:g')
id=$(npm run server  &> >(sed -E -e 's:(^.*)(id/)(.*$):\3:g'))
注意:这只解决了原始尝试中显然存在一些可操作性问题的部分。这不考虑任何因素,除了引用的输出字符串的前提,您应该从运行命令中获得该字符串即,我使用以下命令复制此命令:

echo 'Please visit http;//mysite.com/id/2318' | sed -E -e 's:(^.*)(id/)(.*$):\3:g'
因此,假设当您运行
npm run server
时,您会得到输出
,请访问http//mysite.com/id/2318'
(顺便说一句,我建议可能是http//而不是http//),那么这个命令应该只返回
id
组件


请注意,如果是stderr: 如果您试图筛选的文本来自stderr而不是stdout,那么实际上您可能需要使用以下内容:

id=$(npm run server | sed -E -e 's:(^.*)(id/)(.*$):\3:g')
id=$(npm run server  &> >(sed -E -e 's:(^.*)(id/)(.*$):\3:g'))
例如,解析未配置的npm服务器的输出:

解决您原来的一行: 我的尝试:

id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p')
id=$(echo npm run server | sed -n 's:.*id\/\(.*\)\n.*:\1:p') 
没什么 正在归还

您可以尝试以下方法:

id=$(npm run server | sed -E -e 's:(^.*)(id/)(.*$):\3:g')
id=$(npm run server  &> >(sed -E -e 's:(^.*)(id/)(.*$):\3:g'))
注意:这只解决了原始尝试中显然存在一些可操作性问题的部分。这不考虑任何因素,除了引用的输出字符串的前提,您应该从运行命令中获得该字符串即,我使用以下命令复制此命令:

echo 'Please visit http;//mysite.com/id/2318' | sed -E -e 's:(^.*)(id/)(.*$):\3:g'
因此,假设当您运行
npm run server
时,您会得到输出
,请访问http//mysite.com/id/2318'
(顺便说一句,我建议可能是http//而不是http//),那么这个命令应该只返回
id
组件


请注意,如果是stderr: 如果您试图筛选的文本来自stderr而不是stdout,那么实际上您可能需要使用以下内容:

id=$(npm run server | sed -E -e 's:(^.*)(id/)(.*$):\3:g')
id=$(npm run server  &> >(sed -E -e 's:(^.*)(id/)(.*$):\3:g'))
例如,解析未配置的npm服务器的输出:



顺便说一句,
npm运行服务器
background本身吗?
npm运行服务器
结尾没有数字。为了解释为什么我的答案冗长,顺便说一句:
foo=$(bar)
等待
bar
退出(至少关闭了它的stdout),然后才为
foo
赋值。我假设您不想等到
npm run server
退出后再继续脚本(除非服务关闭stdout和自后台!),所以这种方法对您不开放;不是http:,对吗?顺便说一句,
npm run server
background本身吗?
npm run server
结尾没有数字。为了解释为什么我的答案冗长,顺便说一句:
foo=$(bar)
等待
bar
退出(至少关闭了它的stdout),然后才为
foo
赋值。我假设您不想等到
npm run server
退出后再继续脚本(除非服务关闭stdout和自后台!),所以这种方法对您不开放;而不是http:,对吗?谢谢,我想我已经检查了又检查了。更好。唯一需要注意的是,如果服务在打印该行后退出(或自后台),那么这将只返回并允许运行脚本的其余部分。(另外,任何附加行中的内容都会被捕获到变量中;我把“长命令的结尾”理解为实际输出是多行的,只有这一行值得关注)。@charlesduff我认为您的解决方案更加健壮,而且您似乎理解OP使用其工作流的实际意图。我更多的是从表面上看出来的,因为我不清楚这些意图,我可以清楚地看到
sed
表达式中的一个错误,该错误很容易纠正,可能已经达到了预期的效果outcome@CharlesDuffy考虑到从搜索结果的角度来看,问题是“在长命令末尾解析数字”是有意义的。如果没有其他问题,这个答案可能会对从中找到它的其他人有所帮助