Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex linux中多行模式的替换_Regex_Linux_Command Line_Sed_Awk - Fatal编程技术网

Regex linux中多行模式的替换

Regex linux中多行模式的替换,regex,linux,command-line,sed,awk,Regex,Linux,Command Line,Sed,Awk,假设我有一个名为text.txt的文件 在text.txt中,我有以下几种模式: /** * @something **/ 我想将此模式替换为空字符串。最简单的Linux命令是什么 “grep”不起作用,因为这是多行模式 我试过“sed”,但没能成功 我想“awk”可能很简单,但“awk”似乎很复杂,我对“awk”不太熟悉 假设我们的输入文件是: $ cat text.txt before /** * @something **/ after 我们可以使用awk过滤掉评论: $ awk

假设我有一个名为text.txt的文件 在text.txt中,我有以下几种模式:

/**
 * @something
**/
我想将此模式替换为空字符串。最简单的Linux命令是什么

  • “grep”不起作用,因为这是多行模式
  • 我试过“sed”,但没能成功
  • 我想“awk”可能很简单,但“awk”似乎很复杂,我对“awk”不太熟悉

  • 假设我们的输入文件是:

    $ cat text.txt
    before
    /**
     * @something
    **/
    after
    
    我们可以使用
    awk
    过滤掉评论:

    $ awk '/\/\*\*/ {c=1; next} /\*\*\// {c=0; next} c==0 {print}' text.txt
    before
    after
    
    awk
    的工作原理是使用一个名为
    c
    的变量作为标志。当我们开始时,
    c=0
    表示我们不在评论中。当注释行的开头出现时,
    /**
    ,我们设置
    c=1
    c
    保持为1,直到注释行的下一个结尾出现
    ***/
    ,在这种情况下
    c
    被设置回0。只有当
    c=0
    时,才打印出该行。打开和关闭注释行之间的任何内容,无论格式如何,都不会打印

    代码看起来很有趣,因为
    /
    *
    都是
    awk
    的活动字符。因此,它们都需要用反鞭子逃脱。因此,例如,用于查找注释行开头的正则表达式类似于
    \/\*\*\*
    ,而用于注释结尾的正则表达式类似于
    \*\*\/

    更复杂的输入文件 假设输入文件具有更复杂的结构,如JS示例所示:

    $ cat file
    something
    /**
     * @something
    **/ random
    hello
    hi /**
     * @something
    **/ bye
    hola
    gracias
    bye
    
    我们可以使用
    awk
    处理此问题,如下所示:

    $ awk -v RS='\\*\\*/\n*' '{sub(/\n*\/\*\*.*/,"",$0); print $0}' file
    something
     random
    hello
    hi 
     bye
    hola
    gracias
    bye
    
    以上是用GNU
    awk
    测试的。由于它使用多字符记录分隔符,因此可能无法与较旧版本的
    awk
    一起使用

    虽然
    awk
    通常逐行读取文件,但在上面的版本中,我们设置了记录分隔符
    RS
    ,以匹配注释的结尾。然后,我们删除从注释开始到记录结束的所有内容,并打印记录

    cat text.txt | egrep -v "[/]" | egrep -v "[*] @" > newtext.txt
    

    可以,但您可能需要根据文件中的其他内容进行轻微修改。

    这里有一个简单的
    awk
    将文本从指定模式中删除:

    cat file
    before
    /**
     * @something
    **/
    after
    
    当您不希望包含开始/结束模式时,这是处理此问题最简单的
    awk
    方法之一:

    awk '/END/{f=0} f; /START/{f=1}'
    

    使用GNU awk for multi char RS将整个文件作为一个字符串读取:

    如果您特别想删除您发布的字符串,那么:

    $ cat file
    foo/**
     * @something
    **/bar and more/**
     * @something
    **/stuff
    
    $ awk -v RS='^$' -v ORS= -v pat='/**
     * @something
    **/' '{
        while ( s=index($0,pat) ) {
            $0 = substr($0,1,s-1) substr($0,s+length(pat))
        }
        print
    }' file
    foobar and morestuff
    
    或者,如果您实际上只是想删除每次出现的
    /**
    /
    之间的所有内容,则只需:

    awk -v RS='/[*][*][^/]+/' -v ORS= '1' file
    foobar and morestuff
    

    您可以通过更改其顺序来简化此操作。这样就不需要
    next
    语句了。请参阅我的帖子。sed不应用于任何多行问题,它严格适用于单行上的替换。awk并不复杂,使用它只需要一个小小的范式转换,因为默认情况下,它提供了许多您必须用其他工具/语言手工编写的功能,用于解析文本文件(例如,读取行、拆分为字段等)但是,一旦你使用过它几次,它就不会比任何其他基于Algol的语言更复杂了。你得到的答案是基于对你的需求的几种不同的解释。如果您提供一个真正具有代表性的输入文件(即至少包含两个要删除的模式的输入文件)和相关的expected output.UUOC,那么您就最有可能得到一个可靠的答案,而要成为一个可靠的解决方案,您需要的不仅仅是轻微的修改
    awk -v RS='/[*][*][^/]+/' -v ORS= '1' file
    foobar and morestuff