如何检查字符串是否包含破折号或灰分中的子字符串?

Ole*_*ndr 3 shell grep string shell-script

这是我正在尝试的内容:

#!/bin/sh
contains() {
    if $(echo $1 | grep -c $2) ; then
        echo "0" # contains
    else
        echo "1" # not contains
    fi
}

myString=$1
mySubsting=$2

contains $myString '$mySubsting'
Run Code Online (Sandbox Code Playgroud)

下面是一个执行示例:

# sh ./myScript abcdef bc
./myTest: line 3: 0: command not found
1
Run Code Online (Sandbox Code Playgroud)

编辑:

最初的问题是:如何在 Bourne Shell 中检查字符串是否包含子字符串?

这是我正在尝试的内容:

  #!/bin/sh
  if echo $1 | grep -q $2
  then
    echo "0"
  else
    echo "1"
  fi
Run Code Online (Sandbox Code Playgroud)

下面是一个执行示例:

$ sh ./myTest "$(systemctl status ntp)" "Active: active"
grep: active: No such file or directory
1
Run Code Online (Sandbox Code Playgroud)

如何正确检查一个字符串是否包含另一个字符串?

小智 9

包含函数的可移植(dash、bash、ksh 等)脚本:

#!/bin/sh

contains() {  if    [ "$1" ] &&            # Is there a source string.
                    [ "$2" ] &&            # Is there a substring.
                    [ -z "${1##*"$2"*}" ]; # Test substring in source.
              then  echo 0;                # Print a "0" for a match.
              else  echo 1;                # Print a "1" if no match.
              fi;
            }

contains "$1" "$2"
Run Code Online (Sandbox Code Playgroud)

其中 0 表示“包含”(真值)。

这将测试为:

 $ contains "test a simple line" simpl
 1

 $ contains "One sentence" "No more"
 0
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 7

Bourne shell 对此有一个构造。这与现代中的相同sh(这看起来更像您正在使用的,Bourne shell 不支持$(...);如果它是 Bourne shell,您会得到不同的错误):

case $1 in
  *"$2"*) printf '"%s" is in "%s"\n' "$2" "$1"
esac
Run Code Online (Sandbox Code Playgroud)

如果你想使用grep,那就是:

if printf '%s\n' "$1" | grep -Fqe "$2"; then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi
Run Code Online (Sandbox Code Playgroud)

或者

if grep -Fqe "$2" << EOF
$1
EOF
then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi
Run Code Online (Sandbox Code Playgroud)

但这只有在不$2包含换行符的情况下才能正常工作。

在任何情况下,您都需要在大多数参数扩展周围加上引号。唯一不需要的地方就在case $1上面,但即使那样case "$1"也不会造成伤害。

关于您的代码的一些说明:

  1. 您不能echo用于任意字符串。在这里,根据echo实现的不同,对于$1like-n或 的值,它会失败foo\bar
  2. 不加引号的参数扩展在 shell 中具有非常特殊的意义。你不想那样做。例如,尝试grep -c $2使用值$2like*root /etc/passwd
  3. grepwithout-F用于正则表达式匹配。您需要-F进行固定字符串(子字符串)搜索(以前是 with fgrep),但是如果$2包含多行,则说明grep -F在输入中搜索这些行的任何内容(grep -F $'a\nb'将查找aor b,而不是$'a\nb'字符串)。
  4. 在 中grep -c $2$2如果以 开头,则 的内容将被视为一个选项-。你想要grep -c -e "$2"grep -c -- "$2"避免这种情况。
  5. 您想使用退出状态而不是标准输出来报告布尔条件。在用exit(exit 0表示真,exit 1( 或任何非零数字,但避免值大于 120) 表示假) 的脚本中。对于函数,请return改用。尽管脚本和函数都将返回上次运行命令的状态。
  6. $(cmd) 扩展到输出cmd(由于再次缺少引号,这里经历了 split+glob)减去尾随的换行符。所以如果cmd输出0\n$(cmd)扩展为0. 因此 running$(cmd)尝试运行名为0. 如果要将 的输出转换为cmd退出状态(因此它可以用作布尔值),则需要(exit "$(cmd)"). 这将启动一个子shell,该子shell 以输出cmd作为其退出代码)。
  7. grep -c计算出现的次数。在这里你不需要有完整的计数,你只需要知道它是否被找到(如果至少有一个匹配)。对于grep -q更有效,因为它停止搜索它找到了一个之后。对于grep不支持(标准)-q选项的古老实现,您可以使用fgrep -le "$2" > /dev/null. 使用-l,fgrep也会在第一次匹配时停止,但输出文件名(我们在此处通过将输出重定向到 来丢弃该文件名/dev/null)。