【问题标题】:A linux shell script to find a string and add a few lines before the string用于查找字符串并在字符串前添加几行的 linux shell 脚本
【发布时间】:2013-01-09 12:42:14
【问题描述】:

我是新手,只是想知道是否有人可以提供帮助:)

我有一个这样的文件:

start1  
12.3  
13.2  
15.3  
end1

如何找到字符串end1并在字符串前添加几行,所以看起来像:

start1  
12.3  
13.2  
15.3  
NaN  
NaN  
end1

但是添加的行数必须取决于特定的数字,比如 5。如果它在 start1 和 end1 之间只有 3 个条目,则添加的行数是 2。

【问题讨论】:

  • 你可以使用tail -2 filename | head -1 得到倒数第二行。从那里,我想你可以很容易地编写一个 shell 脚本,使用该行的字符串值和最后一行的值。
  • What have you tried 你在哪里卡住了?

标签: linux string shell sed


【解决方案1】:

您可以使用awk(1) 轻松做到这一点:

awk '/start1/ {start=NR} /end1/ && start {for (i=NR-start;i<=5;++i) {print "NaN"}} 1'

这将记录字符串start1在哪一行,当它看到字符串end1的行时,它将输出最多5行NaN,具体取决于start1end1之间的距离.将 5 更改为您需要的任何值。

【讨论】:

  • 这对我来说很好,这正是我想要的!谢谢 camh :) xxx
  • 保存行号的好主意。您可能希望使用 -v 选项传递值 5
【解决方案2】:

真的不清楚你提到的那个数字是你从文件内容中得出的,还是你可以编程的,但试试这个:

awk '
/start/ { c=0 }
/end/   { for (i=1; i<c; i++) print "NaN" }
{ print; ++c }
' file

如果有任何问题,请告诉我们。

编辑:如果存在少于 5 行,则添加 c 行:

awk '
/start/ { c=0 }
/end/ && c<5  { for (i=1; i<c; i++) print "NaN" }
{ print; ++c }
' file

或最多填充 5 行:

awk '
/start/ { c=0 }
/end/   { for (i=c; i<=5; i++) print "NaN" }
{ print; ++c }
' file

【讨论】:

  • 嗨,Ed,很抱歉我不是很清楚。我需要首先检查 start1 和 end1 之间的条目数。如果条目数少于5,我需要添加额外的行。所以我做了类似 count=`awk'/start1/{c=-2}{c++}/end1/{print c}'
  • 如果 ["$count" -ne 5] 然后加上"NaN"
  • 然后只测试计数器变量c。我现在将更新我的脚本以显示这一点。
【解决方案3】:
awk -vt=5 '/start1/{print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' file

您只需替换上面单行中的 5 即可获得不同数量的“NaN”:)

编辑:开始可能不在第一行。

awk -vt=5 '/start1/{i=0;print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' file

测试

kent$  cat t
Empty lines followed




foo
foo1
start1  
12.3  
13.2  
15.3  
end1
bar
bar2

kent$  awk -vt=5 '/start1/{i=0;print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' t
Empty lines followed




foo
foo1
start1  
12.3  
13.2  
15.3  
NaN
NaN
end1
bar
bar2

【讨论】:

  • 这假定start1 在第一行,而问题只询问startend1 之间的条目数,而不是它们在文件中的位置。
  • 非常感谢!有用!! :D xxx 但这是否取决于开始是否在第一行?我实际上需要找到字符串 start1...
  • @Babycece 是的,我假设“start1”位于第一行。将i=0; 添加到/start1/ 块应该可以解决它,我会更新答案
  • 另一个愚蠢的问题:如何从文件中读取并将其输出回同一个文件中? :)
  • @Babycece 与 awk 不能直接执行(不像 sed -i),但是您可以将输出重定向到 tmp 文件,然后将其 mv 回到原来的后面。 (请做好备份)。 cmd 看起来像 awk 'blahblah' /path/myfile &gt;/tmp/t.tmp &amp;&amp; mv -f /tmp/t.tmp /path/myfile
【解决方案4】:

你可以使用sed来做这样的事情:

`sed /end1/lineToAdd0\nlineToAdd1\netc\nend1/g < file`

我不确定\n,我不记得是不是sed以特殊方式解释它。

【讨论】:

  • 在 sed 中表示换行符的可移植方式是转义的
【解决方案5】:

我承认我不知道用 Sed 做你想做的事情的简单方法。有人可能会发布一个 Awk 答案,这很好,但如果有人不介意启动 Perl 解释器的运行时成本,这也可以:

perl -we 'print until eof() or ($_ = <>) =~ /^start1\s*$/; exit if eof(); print; my $i = 5; --$i, print until eof() or ($_ = <>) =~ /^end1\s*$/; --$i, print "NaN\n" until $i <= 0; print; print <>;'

【讨论】:

    【解决方案6】:

    这更适合awk 只需将c 设置为您需要的数字:

    $ awk -vc=5 '/start/{n=0}/end/{for(i=0;i++<c+1-n;)print"NaN"}++n' file
    start1  
    12.3  
    13.2  
    15.3  
    NaN
    NaN
    end1
    
    $ awk -vc=8 '/start/{n=0}/end/{for(i=0;i++<c+1-n;)print"NaN"}++n' file
    start1  
    12.3  
    13.2  
    15.3  
    NaN
    NaN
    NaN
    NaN
    NaN
    end1
    

    【讨论】:

      【解决方案7】:

      这可能对你有用(GNU sed):

      sed -r '/^start/!b;n;:a;/\nend/bb;$!{N;ba};:b;/(\n[^\n]*){5}/!s/$/\nNaN/;tb;s/(\nend[^\n]*)(.*)/\2\1/' file
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-30
        • 2012-11-02
        相关资源
        最近更新 更多