Shell 测试以查找字符串中的模式

Shell 测试以查找字符串中的模式

我只是想问是否有任何命令可以在常见的 shell(bash、dash、kornshell)上运行?它应该检查line变量是否包含路径的任何部分。

if [[ $line =~ "$PWD"$ ]] ;then

答案1

在任何 POSIX 兼容 shell 中,您可以执行以下操作:

case $line in (*"$PWD"*)
#    whatever your then block had
;;esac

这适用于bashdash、 以及您能命名的任何其他 shell。

它还可以用来轻松处理多种可能性。例如:

case $line in 
(*"$PWD"*)
    echo \$PWD match\!
;;
(*"$OLDPWD"*)
    echo \$OLDPWD match\!
;;
(*)
    ! echo no match\!
;;esac

您还可以使用交替:

case $line in (*"$PWD"*|*"$OLDPWD"*)
    echo '$OLDPWD|$PWD match!'
;;esac

请注意上面引用的使用:

  1. case $line ...
    • 语句的对象case不会被拆分$IFS或用作文件名 gen 的模式。这类似于[[测试中左侧参数的处理方式。
  2. (*"$PWD"*)
    • 这里,shell 扩展不受$IFS或 文件名生成的影响 - 不带引号的扩展既不会分割也不会通配。
    • 但是这里未加引号的扩展可能会被解释为一种模式而不是文字字符串,因此扩展可能意味着不止一件事,具体取决于它是否被引用。
    • 引用应该按字面解释的模式中使用的任何变量很重要,就像引用要按字面解释的模式字符一样。
    • 例如,如果$PWD包含 a*并且未加引号,它将被解释为模式对象,而不是要*搜索的文字。

答案2

是的,最新版本的 bash 可以做到这一点:

$ pwd
/home/terdon
$ line="I'm in /home/terdon"
$ [[ "$line" =~ "$PWD"$ ]] && echo yes
yes

相同的语法适用于 zsh 和 ksh,但不适用于 dash。据我所知,dash没有这样的能力。

请注意,您的正则表达式正在检查变量是否$line 结束$PWD。要检查$PWD中的任何位置是否匹配$line,请删除$

$ line="I'm in /home/terdon, are you?"
$ [[ "$line" =~ "$PWD" ]] && echo yes
yes

答案3

您可以使用带有 shell 替换的条件行:

if [ "$line" != "${line#*$PWD}" ] ; then
    echo "Path found in line"
fi

这是通过尝试使用 shell 参数扩展从 $line 中删除 $PWD 的值来实现的。如果字符串不匹配,则删除成功,并且 $PWD 的值在该行中(即 $line 包含 $PWD)。

但请注意,如果您正在进行路径匹配,这在语义上可能不是您想要的。例如,如果 $PWD 是“/bin”,而 $line 是“/sbin:/usr/bin”,您将在 /usr/bin 上得到误报匹配(因为“/bin”与该匹配)。

这是符合 POSIX 标准的并且应该可以在所有 shell 中工作。

相关内容