我正在编写一个脚本,我需要确保字符串包含逗号。如果它不是我需要脚本退出。考虑下面的内容,我的目的是仅使用内置函数来提高性能:
#!/bin/sh
check_for_commas='This string must contain a comma'
comma_found='0'
iterate_through_string="$check_for_commas"
while [ -n "$iterate_through_string" ]; do
char="$(printf '%.1s' "$iterate_through_string")"
if [ "$char" = ',' ]; then
comma_found='1'
break
fi
iterate_through_string="${iterate_through_string#?}"
done
if [ "$comma_found" != '1' ]; then
echo 'Your string does not contain a comma. Exiting...'
exit
else
echo 'Found a comma in the string. Script can continue...'
fi
我在这个脚本中使用命令替换,它为它迭代的每个字符生成一个子shell。与此相比:
#!/bin/sh
check_for_commas='This string must contain a comma'
if [ "$(echo "$check_for_commas" | grep -q -F ','; echo "$?")" = '1' ]; then
echo 'Your string does not contain a comma. Exiting...'
exit
else
echo 'Found a comma in the string. Script can continue...'
fi
我显然不介意做一些额外的工作来挤出额外的表现。但是我担心使用这么多子壳已经打败了我的整个初衷。
当无意中使用子壳进入画面时,我对仅使用内置增强性能的追求是否变得毫无用处?
答案 0 :(得分:3)
命令替换,如$(printf ...)
,确实很昂贵 - 并且你不需要它们用于你在这里做的事情。
case $check_for_commas in
*,*) echo "Found a comma in the string";;
*) echo "No commas present; exiting"; exit 1;;
esac
在更一般的情况下 - 仅fork()
成本低于fork()/execve()
对,因此拥有单个子shell比单个外部命令调用更便宜;但是如果你比较一个生成多个子shell的循环与一个外部命令调用的比较,这个更便宜取决于你的循环迭代次数(以及你的操作系统中每个东西的价格有多贵 - 分叉是传统上在Windows上比较昂贵,并且就像这样一个事实密集型调查。 :)
(说到最初提出的代码 - 请注意,ksh93会优化特定fork
案例中的var=$(printf ...)
;相比之下,在bash中,您需要使用printf -v var ...
来得到同样的效果)。
答案 1 :(得分:1)
这是一个简短的 POSIX shell函数,它使用组合的删除匹配的前缀模式和删除匹配的后缀模式和{{ 1}},(或者更确切地说test
这是相同的事情),如果有逗号,则返回 true 标志:
[
没有逗号的示例:
chkcomma(){ [ "${1#${1%,*}}" ] ; }
输出:
chkcomma foo && echo comma found || echo no comma
逗号示例:
no comma
输出:
chkcomma foo,bar && echo comma found || echo no comma
这可以进一步抽象,以使用globbing找到子字符串:
comma found
示例:
# Usage: instr globpattern string
# returns true if found, false if not.
instr(){ [ "${2#${2%${1}*}}" ] ; }
输出:
instr '[Mm]oo' mood && echo found