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