我想创建一个bash函数,其行为如下:
?mean
或c
的任何标志,我们将其删除。例如:
d
这是我尝试过的:
my_func 'cmd pattern' 'ab' #=> cmd -ab pattern
my_func 'cmd -a pattern' 'ab' #=> cmd -ab pattern
my_func 'cmd -ac pattern' 'ab' #=> cmd -ab pattern
my_func 'cmd -aef pattern' 'ab' #=> cmd -efab pattern
my_func 'cmd -deaf pattern' 'ab' #=> cmd -efab pattern
我正在为最后一个奋斗。我不确定是否可以,但是很想知道是否可以。
它将以某种方式捕获标志(function my_func() {
echo $1 |
# case with no flags
sed "/^cmd [^-]/s/^cmd \(.*$\)/cmd -$2 \1/" |
# case with flags in $2 or `a` or `b`
sed "/^cmd -[$2ab]+ /s/^cmd -[$2ab] \(.*$\)/cmd -$2 \1/" |
# case with other flags
sed ...
}
)
然后从捕获组(该组上的cmd -\([a-z]\)
)中删除abcd
然后采用该值并将sed 's/[abcd]//g'
附加在输出中。
知道使用ab
以外的其他方法是否存在更好的实现也很酷
答案 0 :(得分:1)
如评论中所述,可能不需要sed。
这是纯bash版本:
my_func(){
local cmd arg1 rest flags
if [[ $2 =~ [^a-zA-Z0-9] ]]; then
echo 1>&2 "bad character in arg2"
exit 1
fi
read -r cmd arg1 rest <<< $1
if [[ $arg1 =~ ^[^-] ]]; then
# no flags
echo "$cmd -$2 $arg1${rest:+ $rest}"
else
# have flags
# strip unwanted/duplicates and append new
eval 'flags=${arg1//[cd'$2']/}$2'
# append new flags and return
echo "$cmd $flags $rest"
fi
}
eval
是危险的,如果传递了不受信任的数据(就像您的sed
使用$2
一样未选中)-始终进行完整性检查-我在这里假设标志必须为字母数字。 / p>
如果您想使用sed,这应该可以工作(关于健全性检查$2
的相同警告:
my_func(){
sed <<< $1 '
/^\([^ ][^ ]*\) \([^-]\)/ { # no flags
s//\1 -'$2' \2/;
q;
}
/^[^ ][^ ]* -\([^ ]*\) .*/ { # has flags
h;
s//\1/;
s/[cd'$2']//g;
G;
s/^\([^\n]*\)\n\([^ ][^ ]* -\)[^ ]*\( .*\)/\2\1'$2'\3/;
q;
}
{
s/.*/#ERROR: malformed input/;
q;
}
'
}