捕获组的Sed替代

时间:2019-05-28 21:18:02

标签: string bash sed

我想创建一个bash函数,其行为如下:

  • 如果传递的字符串没有标志,则将第二个参数添加为标志
  • 如果传递了第二个参数中的任何标志,请将其保留在标志中。
  • 如果传递带有字母?meanc的任何标志,我们将其删除。
  • 如果标志中还有其他字符,我们希望保留这些字符并将第二个参数附加为标志。

例如:

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以外的其他方法是否存在更好的实现也很酷

1 个答案:

答案 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;
        }
    '
}