附加到不以空格开头的非空行和后面两行,一行不以空格开头的非空行

时间:2016-03-17 23:16:35

标签: perl awk sed

我正在将几个不守规矩的早期90年代DOS生成的文本文件转换为更有用的东西。我需要将一组字符附加到所述文本文件中的所有非空行中,这些行不是以空格开头,后面是两行,另一行是非空行不是以空格开头(我将把满足这些特征的所有单行文本称为“目标”行)。与此问题无关的BTW是每条目标线下方直接行的特征。

令人感兴趣的是,上述文本文件中的所有目标行都以相同的字符结尾。此外,我正在寻找的命令需要插入一个相当长的管道。

假设我有以下文件:

foo

third line foo

fifth line foo
 this line starts with a space foo
 this line starts with a space foo

ninth line foo

eleventh line foo

 this line starts with a space foo

last line foo

我希望输出看起来像这样:

foobar

third line foobar

fifth line foo
 this line starts with a space foo
 this line starts with a space foo

ninth line foobar

eleventh line foo

 this line starts with a space foo

last line foo

虽然我正在寻找一种sed解决方案,但也欢迎使用awk和perl。所有解决方案都必须能够在管道中使用。同样欢迎处理更一般情况的解决方案(例如,能够将所需文本附加到以各种方式结束的目标行,包括空格)。

现在,对于背景故事:

我最近几天前问了一个与主题相似的问题(见here)。如你所见,我得到了一些很好的答案。然而,事实证明,我并没有完全理解我的问题,所以我没有问到能够解决问题的正确问题。

现在,我问的是正确的问题!

基于我通过仔细检查上面链接的问题的答案而学到的东西,我拼凑了以下sed命令

sed '1N;N;/^[^[:space:]]/s/^\([^[:space:]].*\o\)\(\n\n[^[:space:]].*\)$/\1bar\2/;P;D' infile

丑陋,是的,但它适用于我的卑微目的。事实上,由于我对此问题的初衷是发布一个问题,然后自我回答相同,您可以看到下面发布的sed构造作为答案之一(由我发布)。

我确信有更好的方法来解决这个问题,但是......任何想法,任何人?

3 个答案:

答案 0 :(得分:0)

从你发布的预期输出看起来你想说"被跟随,两行向下,一行不是以空格开头"而不是"跟随,两行向下,一行 DOES 以空格开头"。

这会产生您显示的输出:

$ cat tst.awk
NR>2 { print p2 ((p2 ~ /^[^[:blank:]]/) && /^[^[:blank:]]/ ? "bar" : "") }
{ p2=p1; p1=$0 }
END { print p2 ORS p1 }

$ awk -f tst.awk file
foobar

third line foobar

fifth line foo
 this line starts with a space foo
 this line starts with a space foo

ninth line foobar

eleventh line foo

 this line starts with a space foo

last line foo

它只保留一个2行缓冲区并添加" bar"在您需要的任何条件下打印到最后一行。它适用于所有POSIX awks以及支持POSIX字符类的任何其他功能(其余部分,将[[:blank:]]更改为[ \t])。

答案 1 :(得分:0)

您过度分析了问题,现在您的问题显示为计算机程序,并且您的程序错误。最好使用示例和实际数据来解释需求,以便我们有希望在头脑中合理化问题

此Perl程序会改变您的算法,以使输出与您所需的输出相匹配

foobar

third line foobar

fifth line foo
 this line starts with a space foo
 this line starts with a space foo

ninth line foobar

eleventh line foo

 this line starts with a space foo

last line foo

输出

<%
    String vlemail=request.getParameter("vlemail");
    try
    {
    String str="jdbc:mysql://localhost:3306/licet";
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    Connection con=null;
    con=DriverManager.getConnection(str,"root","");
    Statement st=con.createStatement(); 
    ResultSet rs =st.executeQuery("select Password from record where Email='"+vlemail+"'");
    while(rs.next())
    {
    String a=rs.getString("Password");
    }
     out.println("Retrieved" );
    }
    catch(Exception e)
    {
    out.println(e);
    out.println("Not retrieved");
    }
    %>

答案 2 :(得分:-1)

这个sed one-liner似乎可以解决OP中概述的具体案例:

sed '1N;N;/^[^[:space:]]/s/^\([^[:space:]].*\o\)\(\n\n[^[:space:]].*\)$/\1bar\2/;P;D' infile

感谢Benjamin W.one of my recent questions的答案中提供的出色的澄清信息,我能够拼凑出这个解决我特定问题的单线程。如果您希望深入了解所述命令,请参阅相同内容。