Regex 删除<;及>;(包括支架)内部无角支架

Regex 删除<;及>;(包括支架)内部无角支架,regex,linux,sed,Regex,Linux,Sed,我必须用sed命令修改类似html的文本。我必须删除以一个或多个字符 例如:来自 aaaccc我想要aaaccc 我可以用它来做这件事 “s/]\+>//g” 但是,如果字符之间为空字符串,或者文本中存在双,则此命令不起作用。 例如,从 aa<>bb<cc>vv<<gg>>h 如何修改它以获得正确的结果?您可以使用 sed 's/<\+[^>]*>\+//g' sed 's/<\{1,\}[^>]*>\{1,\

我必须用sed命令修改类似html的文本。我必须删除以一个或多个
字符

例如:来自
aaaccc
我想要
aaaccc

我可以用它来做这件事

“s/]\+>//g”

但是,如果
字符之间为空字符串,或者文本中存在双
,则此命令不起作用。 例如,从

aa<>bb<cc>vv<<gg>>h
如何修改它以获得正确的结果?

您可以使用

sed 's/<\+[^>]*>\+//g'
sed 's/<\{1,\}[^>]*>\{1,\}//g'
sed -E 's/<+[^>]*>+//g'
每个sed命令的结果是您可以使用的
aabbvvh

sed 's/<\+[^>]*>\+//g'
sed 's/<\{1,\}[^>]*>\{1,\}//g'
sed -E 's/<+[^>]*>+//g'

每个sed命令的结果都是
aabbvvh

问题在于,一旦允许嵌套
字符,就可以将语言类型从“常规”转换为“上下文无关”

正则语言是由正则表达式匹配的语言,而上下文无关语法通常不能由正则表达式解析。嵌套的无限级别是阻碍这一点的原因,需要一个基于堆的自动机来解析这些语言

但是,这里有一点复杂的解决方案,如果你认为你所面临的文本中嵌套的水平有上限,那么你可以转换成一种不规则的语言,这是基于不规则情况永远不会发生的前提:

假设您的模式中嵌套的级别不会超过三级(这允许您查看模式并能够将其扩展到N级),您可以使用以下算法构建正则表达式,该正则表达式将允许您匹配三级嵌套,但仅此而已(您可以创建一个regexp来解析N个级别,但除此之外,这是regexps的umbounded-bounded-bounded特性:))


让我们自下而上递归地构造表达式。只有一个嵌套级别,您只有
,在内部找不到这两个字符(如果您允许
,问题是一旦您允许嵌套
字符,您就可以将语言类型从“常规”转换为“无上下文”

正则语言是由正则表达式匹配的语言,而上下文无关语法通常不能由正则表达式解析。嵌套的无限级别是阻碍这一点的原因,需要一个基于堆的自动机来解析此类语言

但是,这里有一点复杂的解决方案,如果你认为你所面临的文本中嵌套的水平有上限,那么你可以转换成一种不规则的语言,这是基于不规则情况永远不会发生的前提:

假设您的模式中嵌套的级别不会超过三级(这允许您查看模式并能够将其扩展到N级),您可以使用以下算法构建正则表达式,该正则表达式将允许您匹配三级嵌套,但仅此而已(您可以创建一个regexp来解析N个级别,但除此之外,这是regexps的umbounded-bounded-bounded特性:))


让我们从下到上递归地构造表达式。只有一个嵌套级别,您只有
,在内部找不到这两个(如果您允许
这很棘手,如果文本是
ab
?相关:当您谈到类似HTML的语言时,您是否可以声明您的输入文件满足格式良好的XML文件的要求?如果是这样,则XML工具的解决方案很简单。这很棘手,如果文本是
ab
?相关:当您谈到类似HTML的语言,你能说明你的输入文件满足格式良好的XML文件的要求吗?如果是这样的话,使用XML工具的解决方案是微不足道的。这仍然会在许多输入字符串上给出错误的输出。@Poton在原始问题下的注释中给出了一个例子。另一个例子-关于输入字符串
将返回
c>
。我认为这种问题在最一般的情况下没有一行解决方案,即使假设“最一般的情况”可以正确定义。@mathguy OP说:我必须删除之间的所有字符串,包括。示例是
aabbvvh
。我知道OP希望将
中的任何子字符串与下一个最近的代码>
进行匹配,在开始/结束处有任何数量的
。因为答案被接受,所以它是正确的正是OP所期望的。您和Poton可能想到的情况很可能不在问题的范围内。我将对其进行编辑,以便将来的读者能够清楚地了解问题涉及的字符串类型。这仍然会在许多输入字符串上给出错误的输出。@Poton在原始问题下的评论中给出了一个示例。另一个例子-输入字符串
上的第三个解决方案将返回
c>
。我认为这种问题在最一般的情况下没有一行解决方案,即使假设“最一般的情况”可以正确定义。@mathguy OP说:我必须删除之间的所有字符串,包括。示例是
aabbvvh
。我知道OP希望将
中的任何子字符串与下一个最近的代码>
进行匹配,在开始/结束处有任何数量的
。因为答案被接受,所以它是正确的这正是OP所期望的。你和波彤可能想到的情况很可能不在问题的范围内。我将对其进行编辑,以便未来的读者能够清楚地了解问题涉及的字符串类型。
sed 's/<\+[^>]*>\+//g'
sed 's/<\{1,\}[^>]*>\{1,\}//g'
sed -E 's/<+[^>]*>+//g'
s='aa<>bb<cc>vv<<gg>>h'
sed 's/<\+[^>]*>\+//g' <<< "$s"
sed 's/<\{1,\}[^>]*>\{1,\}//g' <<< "$s"
sed -E 's/<+[^>]*>+//g' <<< "$s"
{l0} = [^<>]*
{l1} = <[^<>]*>
{l2} = <{l0}({l1}{l0})*> = <[^<>]*(<[^<>]*>[^<>]*)*>
{l3} = <{l0}({l2}{l0})*> = <[^<>]*(<[^<>]*(<[^<>]*>[^<>]*)*>[^<>]*)*>
{lN} = <{l0}({l(N-1)}{l0})*>
<[^<>]*(<[^<>]*(<[^<>]*>[^<>]*)*>[^<>]*)*>
{l3--------------------------------------}
<{l0--}({l2---------------------}{l0--})*>
        <{l0--}({l1----}{l0--})*>
                <{l0--}>          
package com.stackoverflow.q61630608;

import java.util.regex.Pattern;

public class NestingRegex {

    public static String build_regexp( char left, char right, int level ) {
        return level == 0
                ? "[^" + left + right + "]*"
                : level == 1
                        ? left + build_regexp( left, right, 0 ) + right
                        : left + build_regexp( left, right, 0 )
                        + "(" + build_regexp( left, right, level - 1 )
                        + build_regexp( left, right, 0 )
                        + ")*" + right;
    }

    public static void main( String[] args ) {
        for ( int i = 0; i < 5; i++ )
            System.out.println( "{l" + i + "} = "
                    + build_regexp( '<', '>', i ) );
        Pattern pat = Pattern.compile( build_regexp( '<', '>', 16 ), 0 );
        String s = "aa<>bb<cc>vv<<gg>>h<iii<jjj>kkk<<lll>mmm>ooo>ppp";
        System.out.println(
                String.format( "pat.matcher(\"%s\").replaceAll(\"@\") => %s",
                               s, pat.matcher( s ).replaceAll( "@" ) ) );
    }


}

{l0} = [^<>]*
{l1} = <[^<>]*>
{l2} = <[^<>]*(<[^<>]*>[^<>]*)*>
{l3} = <[^<>]*(<[^<>]*(<[^<>]*>[^<>]*)*>[^<>]*)*>
{l4} = <[^<>]*(<[^<>]*(<[^<>]*(<[^<>]*>[^<>]*)*>[^<>]*)*>[^<>]*)*>
pat.matcher("aa<>bb<cc>vv<<gg>>h<iii<jjj>kkk<<lll>mmm>ooo>ppp").replaceAll("@") => aa@bb@vv@h@ppp
sed 's/<[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>//g' file1.xml
l0="[^<>]*"
l1="<${l0}>"
l2="<${l0}\(${l1}${l0}\)*>"
l3="<${l0}\(${l2}${l0}\)*>"
l4="<${l0}\(${l3}${l0}\)*>"
l5="<${l0}\(${l4}${l0}\)*>"
l6="<${l0}\(${l5}${l0}\)*>"
echo regexp is "${l6}"
regexp is <[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*\(<[^<>]*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>[^<>]*\)*>
sed -e "s/${l6}/@/g" <<EOF
aa<>bb<cc>vv<<gg>>h<iii<jj<>j>k<k>k<<lll>mmm>ooo>ppp
EOF
aa@bb@vv@h@ppp