【问题标题】:How do I replace/filter out "$\n (quote end-of-line newline) using grep, awk, and sed in bash?如何在 bash 中使用 grep、awk 和 sed 替换/过滤掉 "$\n (quote end-of-line newline)?
【发布时间】:2019-03-05 16:00:29
【问题描述】:

我有一个 Java 项目,其中有很多行如下所示:

myMethod("some text here ..."
+ " ... more text here"
+ " ... and even more text here");

我需要为此执行 bash 搜索:

"some text here ... ... more text here ... and even more text here";

我尝试过这样的事情:

# Filtering for text between the two parenthesis
$ grep -rn "myMethod" . | awk -F\( '{print $2}' | awk -F\) '{print $1}' | sort | uniq

# replacing the `"$\n` with nothing
$ grep -rn "myMethod" . | sed -e 's/"$\n\s//g' | sort | uniq

# same
$ grep -rn "myMethod" . | sed -e ':a;N;$!ba;s/"$\n/,/g' | sort | uniq

但是,这些都没有给我我想要的东西,即传递给 myMethod 方法的所有唯一字符串。

那么,如何在 bash 中使用 grep、awk 和 sed 替换或过滤 "$\n(引用行尾换行符)?

【问题讨论】:

  • 能否请您在您的帖子中提供预期输出示例并告诉我们。
  • @RavinderSingh13 当我说“我需要为此执行 bash 搜索:“这里有一些文本……这里有更多文本……这里有更多文本”时,我做到了。本质上,两个括号之间的文本。
  • 通过查看您的个人资料了解到您几乎没有选择任何答案作为正确答案,请在某个时间给出它,当您看到帖子的答案很少时,尝试选择任何答案(最适合您的问题)作为正确的一个。您也可以针对您之前提出的问题(如果适用)这样做,谢谢。
  • @RavinderSingh13 如果您愿意进一步看,您会发现我经常选择一个答案作为正确答案。但是,如果没有答案是正确的答案,我就不能这样做。
  • 是的,这就是为什么我提到它适用的地方,不用担心。继续分享和学习 SO,干杯。

标签: bash awk sed grep


【解决方案1】:

试试这个(GNU grepGNU sed,我相信你正在使用它们):

$ cat file
myMethod("some text here ..."
+ " ... more text here"
+ " ... and even more text here");

$ grep -rzn "myMethod" . | sed -rn '/myMethod/{:a;s/\)//;tb;N;ba;:b;s/\n//g;s/[^"]*$//;:c;s/^[^"]*"([^"]*)"(.*)/\2\1/;tc;p;}'
some text here ... ... more text here ... and even more text here

$ grep -rzn "myMethod" . | sed -rn '/myMethod/{:a;s/\)//;tb;N;ba;:b;s/\n//g;s/[^"]*$//;:c;s/^[^"]*"([^"]*)"(.*)/\2\1/;tc;s/^/"/;s/$/";/;p}'
"some text here ... ... more text here ... and even more text here";

我相信它适用于多个文件和多次出现。
我使用sed 逐行读取,直到找到接近的括号),然后连接。

【讨论】:

    【解决方案2】:

    这是您想要做的(使用 GNU sed 处理 -z 并识别 \n)?

    $ sed -z 's/"\n+ "//g' file
    myMethod("some text here ... ... more text here ... and even more text here");
    
    $ sed -z 's/"\n+ "//g' file | sed -n 's/^myMethod("\([^"]*\).*/\1/p'
    some text here ... ... more text here ... and even more text here
    

    如果传递给 myMethod 的字符串可以包含转义的"s,那么您只需要告诉我们它们是如何转义的(加倍?反斜杠?其他什么?)然后它们就很容易处理了。

    【讨论】:

      【解决方案3】:

      试试这是否适合你:

      awk -F'"' '/^myMethod\(/,/\);$/{str = str " " $2}END{print str}' file
      

      对于您的输入,这将产生“这里有一些文字......这里有更多文字......这里还有更多文字”。如果需要,您可以轻松修复前导空格。

      基本上使用范围模式:只在字符串myMethod(和函数调用结束);之间搜索,然后抓取并连接$2。但是,如果同一行上有多个函数参数,这将不起作用。您可能还需要考虑myMethod( 之前和); 之后的空格。

      【讨论】:

        【解决方案4】:

        完全适用于您提供的字符串和格式(包括引号和“+”符号)的内容如下所示:

        >cat my_file.txt
        myMethod("some text here ..."
        + " ... more text here ..."
        + " ... and even more text here");
        other lines
        and some other");
        
        >sed -n '/myMethod/,/");/p' my_file.txt | sed -e ':a;N;$!ba;s/\n/ /g' -e "s/\"//g" -e "s/\+//g" -e "s/myMethod//g"
        (some text here ...   ... more text here ...   ... and even more text here);
        

        first sed 提取字符串 [myMethod] 和第一次出现的字符串 [");] 之间的所有内容

        然后我们有另一个 sed,第一个表达式消除了所有换行符,第二个表达式消除了双引号,第三个表达式消除了“+”符号,最后一个表达式从最终输出中删除了“myMethod”字符串

        如果你想这么荒唐,你可以加上[-e "s/[()]/\"/g"] 把输出的前后括号(),变成双引号"

        L.E:如果您的代码中有以下任何字符,这显然会弄乱您的代码:[+"()myMethod]

        【讨论】:

        • 我试过grep -rn "myMethod" | xargs -i sed -n '/myMethod/,/");/p' {} | sed -e ':a;N;$!ba;s/\n/ /g' -e "s/\"//g" -e "s/\+//g" -e "s/myMethod//g",但没用。
        • 但您在命令开头执行grep -rn "myMethod",这是管道后 xargs 的输入。这个grep 的原因是什么?你在用grep 做什么。你需要一个输入文件。
        • 我正在使用grep 在我的项目结构中查找所有使用myMethod 的类,然后删除"$\n,这样我就可以在一行中获取整个方法调用。跨度>
        • 所以你想在原位更改ALL你的文件,将方法重写为一行。您只提到您希望将方法的内容作为单行显示在屏幕上。或者我误解了......
        【解决方案5】:

        这将遍历(在当前目录中本地)包含字符串 myMethod 的所有文件,读取该方法直到包含信号 ); 并用一个衬里替换它:

        >>cat my_file.txt
        random first line
        random second line
        
        myMethod(first line of code
        second line of code
        third line of code);
        # notice above method ending in string ");". This is important to mark the enclosing of the method.
        # this string should not be present anywhere else withing the content of the method
        
        other lines
        and some other");
        
        >>cat other_file.txt
        myMethod("text in other file ..."
        + " ... yet more text from other file ..."
        + " ... and even more text here from the second file"); # ending of method
        other lines
        and some other");
        
        ACTUAL COMAND
        >>for file_containing_myMethod in `grep -l "myMethod" *`; do ONE_LINER=`sed -n '/myMethod/,/);/p' ${file_containing_myMethod} | sed -e ':a;N;$!ba;s/\n/ /g'`; sed -i "/myMethod/,/);/{/);/ s/.*/${ONE_LINER}/; t; d}" ${file_containing_myMethod}; done
        random first line
        random second line
        
        myMethod(first line of code second line of code third line of code);
        # notice above method ending in string ");". This is important to mark the enclosing of the method.
        # this string should not be present anywhere else within the content of the method
        
        other lines
        and some other");
        
        myMethod("text in other file ..." + " ... yet more text from other file ..." + " ... and even more text here from the second file"); # ending of method
        other lines
        and some other");
        

        请注意,当您测试时,您应该从最后一个sed 中删除-i 标志。 -i 会立即更改/重写您的文件,而在测试之前您不希望这样做。

        【讨论】:

          【解决方案6】:

          不需要其他工具;这可以单独使用 bash 完成。

          $ s=$'myMethod("some text here ..."\n+ " ... more text here"\n+ " ... and even more text here");'
          $ echo "$s"
          myMethod("some text here ..."
          + " ... more text here"
          + " ... and even more text here");
          $ t="${s//$'\n'/ }"
          $ t="${t//\" + \"/ }"
          $ t="${t#myMethod(\"}"
          $ t="${t%\");}"
          $ echo "$t"
          some text here ...  ... more text here  ... and even more text here
          

          这使用了一个名为“模式替换”的 bash 功能,它是“参数扩展”的一部分,您可以在 bash 的手册页或官方 bash documentation 上阅读。

          【讨论】:

          • 我只是以那些字符串片段(例如,“这里的一些文本......”)为例。文本应该是方法参数中的任何内容。可以是任何文本。
          • @Brian,您的问题询问如何在 bash 中执行此操作,因此我提供了 bash 解决方案。如何将多行文本放入源变量取决于您。 :) 您当然可以使用模式替换来删除源变量中出现的任何文本,包括myMethod("
          • @Brian .. 好的,我已经更新了我的示例,以包括对源数据的一些额外修剪。请阅读参数扩展。
          猜你喜欢
          • 1970-01-01
          • 2011-12-03
          • 2020-02-03
          • 1970-01-01
          • 1970-01-01
          • 2022-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多