子字符串和正则表达式

子字符串和正则表达式

我的变量中包含一个字符串,我想根据相对于另一个子字符串的位置提取子字符串。除非字符串作为参数发送到函数,否则我的解决方案似乎有效。我正在使用 bash shell。

#!/usr/bin/bash

var0="-a check one two three"
var1="check"

function getsubstr() {
echo ${*#*"${2}"} 
}

# this prints 'one two three' which is what I want
echo ${var0#*"${var1}"}

# this prints '-a one two three', not what I want.
getsubstr $var0

请注意,当我放入echo $*函数时,它会打印与(-> '-a check one 二三')getsubstr相同的字符串,而当我放入函数时,它会打印与(-> 'check')相同的字符串。所以,在我看来,我要求在两种情况下打印相同的子字符串。$var0echo $2getsubstr$var1

另一个难题是,如果不是echo ${*#*"${2}"}getsubstr我使用的函数中echo ${*%"${2}"*},我得到完全相同的结果。

任何有助于理解这种行为的帮助将不胜感激。

顺便说一句,我意识到 函数${*:3}内部getsubstr可以返回我想要的子字符串,但我试图理解#*<regexp>%<regextp>*行为。

答案1

getsubstr $var0正在向函数传递 5 个参数。
另外,$* 和 $@ 测试每个人1 美元 2 美元等..arg 反对#图案。

关于正则表达式bash:我在最后添加了一些示例,顺便说一句,“*”只是一个特殊正则表达式字符当它在正则表达式上下文中使用时,即。使用时 =~。在第一次使用 * in 时${*,星号的特殊用途是(伪)名称一个 var 扩展为所有变量的串联: $1 $2 $...等...
第二次使用星号,在#*"${2}", 中意味着“$2” 前面没有任何内容,将分别/单独地与每个传递的 $1 等参数进行匹配。

以下脚本可能对 $@ 和 $* 有帮助(例如)...

#!/bin/bash
#   
getsubstr() {
  echo -n " ${#@} args";
  [[ "$1$2$3$4$5$6" == *\ * ]] && echo " (with embedded spaces)" || echo " (no spaces)"
  echo '                  "${*}"          '\|"${*}"\|
  echo '                   ${*}           '\|${*}\|
  echo '                  "${@}"          '\|"${@}"\|
  echo '                   ${@}           '\|${@}\|
  echo '                  "${*#*"${2}}"   '\|"${*#*"${2}"}"\|
  echo '                   ${*#*"${2}}    '\|${*#*"${2}"}\|
  echo '                  "${@#*"${2}}"   '\|"${@#*"${2}"}"\|
  echo '                   ${@#*"${2}}    '\|${@#*"${2}"}\|
  echo '                        ${*#B}    '\|${*#B}\|
  echo '                       "${*#B}"   '\|"${*#B}"\|
  echo '                        ${@#B}    '\|${@#B}\|
  echo '                       "${@#B}"   '\|"${@#B}"\|
}
var0="a B c      "
echo
echo -n "Passing "; getsubstr "$var0" ; echo
echo -n "Passing "; getsubstr  $var0  ; echo
echo -n "Passing "; getsubstr "$var0" "$var0" ; echo
echo -n "Passing "; getsubstr  $var0   $var0  ; echo
echo
exit 
###################################################################

正则表达式在bash

# Regex checks: "=~" uses extended regular expression
#+  Parenthesized subexpressions within the regular expression are saved
#+  in the array variable BASH_REMATCH
#+  $BASH_REMATCH / ${BASH_REMATCH[0]} is the string matching the entire regular expression. 
#+  ${BASH_REMATCH[n]} is the sub string matching the nth parenthesized subexpression

  [[ "abcdef" =~ (.)(.)(.) ]] && echo "# $BASH_REMATCH"
# abc

  [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[0]}"
# abc

  [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[2]}"
# b

  [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[@]}"
# abc a b c

答案2

更新并附有解释

您看到这种类型行为的原因是因为$*或什至$@扩展到所有位置参数:$1$2。当您尝试执行参数扩展(PE) 在这两个特殊变量之一上,您将 PE 应用于每个位置参数,并且不是单个字符串。

摘自man bash

${参数#word}
删除匹配的前缀模式。该单词被扩展以产生一个模式,就像路径名扩展一样。如果模式与参数值的开头匹配,则扩展的结果是参数的扩展值,并#'' case) or the longest matching pattern (the删除了最短匹配模式(##''情况)。 如果参数是@或*,则依次对每个位置参数应用模式删除操作,并且扩展是结果列表。

本质上你正在做的是这样的:

getsubstr() { 
  tmp=$2
  for arg; do 
    printf "%s " ${1#*$tmp}
    shift
  done
}

以下函数通过设置$*临时变量来工作$tmp,因为您现在将 PE 应用于普通变量一次。

getsubstr() {
  tmp=$*
  echo ${tmp#*$2}
}

聚苯乙烯

不要使用它function,因为它不是 POSIX,而且如果您已经()在函数名称之后使用它,实际上完全没有必要。

聚苯硫醚

这实际上与常用表达反而球形表达式。更正式地说,这些被称为参数扩展

相关内容