Regex 使用sed提取行中的特定字符串

Regex 使用sed提取行中的特定字符串,regex,bash,unix,awk,sed,Regex,Bash,Unix,Awk,Sed,在这样一行字符串中: "<testcase_name> +config=<main_cfg> +cfg1=<cfg1> +cfg2=<cfg2> +testlength=<string> +print_cfg=<string> +print_match=<string> +quit_count=<string>" 请注意,分隔了cfg1和cfg2字符串。是否有一行(如果可能在sed中)可以做到这一点

在这样一行字符串中:

"<testcase_name> +config=<main_cfg> +cfg1=<cfg1> +cfg2=<cfg2> +testlength=<string> +print_cfg=<string> +print_match=<string> +quit_count=<string>"
请注意,
分隔了
cfg1
cfg2
字符串。是否有一行(如果可能在sed中)可以做到这一点

更多条件:

  • +cfg1
    +cfg2
    可以是任何字符串,并且可以有更多字符串。所以这里的关键是不要包括这些已知的配置:
    testlength
    config
    print\u match
    print\u cfg
    ,以及
    quit\u count
  • 除了总是第一个配置的
    +config=
    之外,配置并不总是按照上述示例的顺序进行
  • (1)中提到的任何已知配置可能不存在于线路中
  • 示例:

    投入1:

    testA+config=reg+input=walk1s+print\u match=1+testlength=short

    预期产出1:

    %other\u cfg=walk1s

    投入2:

    testA+config=mem+quit\u count=50+order=reverse+input=rand+testlength=long

    预期产出2:


    %other\u cfg=reverse.rand

    如果
    +cfg1
    +cfg2
    保证在行中始终处于该顺序,则为是;只需替换其他所有内容:

    sed 's/.*+cfg1=<//;s/>.*+cfg2=<//;s/>.*//'
    
    sed的/*+cfg1=.*+cfg2=.*/'
    

    否则,您至少需要
    awk

    sed用于在单个行上进行简单替换,仅此而已。这不是问题所在,所以这不是sed的工作,而是awk的工作

    $ cat file
    "<testcase_name> +config=<main_cfg> +cfg1=<cfg1> +cfg2=<cfg2> +testlength=<string> +print_cfg=<string> +print_match=<string> +quit_count=<string>"
    testA +config=reg +input=walk1s +print_match=1 +testlength=short
    testA +config=mem +quit_count=50 +order=reverse +input=rand +testlength=long
    
    $ cat tst.awk
    BEGIN{
        FS="[ =]+"
        split("config testlength print_match print_cfg quit_count",tmp)
        for (i in tmp) {
            skip_cfgs["+"tmp[i]]
        }
    }
    {
        other_cfg = ""
        for (i=2;i<=NF;i+=2) {
            if ( !($i in skip_cfgs) ) {
                other_cfg = (other_cfg=="" ? "" : other_cfg ".") $(i+1)
            }
        }
        print "% other_cfg =", other_cfg
    }
    
    $ awk -f tst.awk file
    % other_cfg = <cfg1>.<cfg2>
    % other_cfg = walk1s
    % other_cfg = reverse.rand
    
    $cat文件
    “+config=+cfg1=+cfg2=+testlength=+print\u cfg=+print\u match=+quit\u count=”
    testA+config=reg+input=walk1s+print\u match=1+testlength=short
    testA+config=mem+quit\u count=50+order=reverse+input=rand+testlength=long
    $cat tst.awk
    开始{
    FS=“[=]”
    拆分(“配置testlength打印匹配打印cfg退出计数”,tmp)
    对于(tmp中的i){
    跳过cfgs[“+”tmp[i]]
    }
    }
    {
    其他_cfg=“”
    对于(i=2;i这可能适用于您(GNU-sed):


    这将用所需字符串替换第一个字符串,并向模式空间添加一个查找表,其中包含所有不需要的配置字符串。然后迭代删除不需要的配置字符串,并将剩余的配置变形为所需的输出。

    Use可以将其用作regex
    (?在示例输入和预期输出上下功夫。例如,您说字段可以是任意顺序,所以至少显示两行示例输入/输出。我们不知道您希望字段输出的顺序是它们在输入中出现的顺序还是其他顺序。您希望用结果填充一个shell变量-一行用于所有输入/输出行r每行输入一个或其他。关于您对多行、多位置输入的要求,您有很多没有告诉我们。@RakholiyaJenish抛出了一些“regexp”某些在线工具认为是有效的是无用的。每个工具都支持不同风格的regexp,因此要提供有用的解决方案,您需要确定您想使用的工具以及需要使用的选项。例如,在任何标准UNIX工具中,regexp都不起作用,例如,sed、awk或grep(不带-P的非GNU)。您还忽略了一点,即OP不希望找到与regexp匹配的字符串,他希望找到与其他字符串列表不匹配的字符串。@renvill那么,您是在告诉我们您的输入文件始终只包含一行吗?如果不是,那么与其给我们显示一组单独的行,不如给我们显示一个多行示例input文件和相关的输出,多行或其他。Hi@EdMorton,如果需求是零碎的,很抱歉。这实际上已经在一个shell脚本中了。因此输入实际上只是一行。具体来说,这行代码就是我要进行配置提取的地方:other\u cfg=`echo$tc | sed-e's/*\+config=[a-z0-9\ux]*//“| sed-e/\+testlength=[a-z0-9\]*/][a-zo-e/\+print.*=[a-z0-9\]*/][a-sed-e/\+.*/][sed-e/][sed-e//''”(这里是shell脚本初学者,抱歉^^^)sed的“这是全部”的一部分,用于在单独的行上进行简单替换,仅此而已。”这根本不是真的,当然有些人可能只想在单个行上使用它进行简单替换。“sed”中的“s”表示流,而不是行;例如,N命令支持多行编辑。在sed中编写函数的能力说明它不仅仅用于“简单”替换。然而sed是轻量级的:-)@peak不,这是真的。我每天都使用sed,已经使用了30多年,但是N命令和除s、g和p(带-N)之外的所有其他sed命令在20世纪70年代中期awk发明时就已经过时了。今天人们只是使用所有其他的东西进行脑力锻炼,awk脚本在几乎所有方面都会更好(例如清晰性、效率、可维护性、健壮性、可移植性,并且通常简洁)。关于“否则,您至少需要awk”的评论严格来说是不正确的(sed是图灵完整的),事实上,在sed中处理键可能处于任意顺序的可能性并不难(例如,如果OP要求允许,字符串可以先规范化)。请参见图灵完整性。当然,通常有很好的理由使用awk而不是sed。注意。我将“需要”改为“想要”。我无法想象脚本如何区分“单词”的位置从
    config…count
    开始,我用输入
    “+config=+print=+cfg2=+testlength=+print\u cfg=+print\u match=+quit\u count=“
    ”(即
    +print=
    而不是
    +cfg1=
    )它输出的是
    other\u cfg=。
    而不是
    other\u cfg=。
    。我不会假装知道它为什么会这样做!@EdMorton说得很对,我过度简化了查找表。具体的配置字符串现在是原样。
    $ cat file
    "<testcase_name> +config=<main_cfg> +cfg1=<cfg1> +cfg2=<cfg2> +testlength=<string> +print_cfg=<string> +print_match=<string> +quit_count=<string>"
    testA +config=reg +input=walk1s +print_match=1 +testlength=short
    testA +config=mem +quit_count=50 +order=reverse +input=rand +testlength=long
    
    $ cat tst.awk
    BEGIN{
        FS="[ =]+"
        split("config testlength print_match print_cfg quit_count",tmp)
        for (i in tmp) {
            skip_cfgs["+"tmp[i]]
        }
    }
    {
        other_cfg = ""
        for (i=2;i<=NF;i+=2) {
            if ( !($i in skip_cfgs) ) {
                other_cfg = (other_cfg=="" ? "" : other_cfg ".") $(i+1)
            }
        }
        print "% other_cfg =", other_cfg
    }
    
    $ awk -f tst.awk file
    % other_cfg = <cfg1>.<cfg2>
    % other_cfg = walk1s
    % other_cfg = reverse.rand
    
    sed -r 's/^\S+\s+(.*)$/other_cfg = \1\n+config=+testlength=+print_match=+print_cfg=+quit_count=/;:a;s/ (\+\S+=)\S+(.*\n.*)\1/\2/;ta;s/ \+[^=]*=/./g;s/\./ /;P;d' file