首页 文章

使用sed或awk在特定行号处插入一行

提问于
浏览
119

我有一个脚本文件,我需要用另一个脚本修改,以在第8行插入文本 .

要插入的字符串: Project_Name=sowstest ,放入名为 start 的文件中 .

我试图使用awk和sed,但我的命令变得乱码 .

8 回答

  • 5

    一个 ed 答案

    ed file << END
    8i
    Project_Name=sowstest
    .
    w
    q
    END
    

    . 在其自己的行上结束输入模式; w 写道; q 退出 . GNU ed有一个 wq 命令来保存和退出,但是旧的ed 's don' t .

    进一步阅读:https://gnu.org/software/ed/manual/ed_manual.html

  • 5

    awk答案

    awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new
    
  • 1
    sed -i '8i8 This is Line 8' FILE
    

    插入第8行

    8 This is Line 8
    

    进入文件文件

    -i 直接修改文件FILE,没有输出到stdout,如glenn jackman的评论中所述 .

  • 196

    POSIX sed (例如OS X的 sed ,下面的 sed )要求 i 后面跟一个反斜杠和一个换行符 . 此外,至少OS X的 sed 在插入的文本后不包含换行符:

    $ seq 3|gsed '2i1.5'
    1
    1.5
    2
    3
    $ seq 3|sed '2i1.5'
    sed: 1: "2i1.5": command i expects \ followed by text
    $ seq 3|sed $'2i\\\n1.5'
    1
    1.52
    3
    $ seq 3|sed $'2i\\\n1.5\n'
    1
    1.5
    2
    3
    

    要替换行,可以使用带有数字地址的 c (更改)或 s (替换)命令:

    $ seq 3|sed $'2c\\\n1.5\n'
    1
    1.5
    3
    $ seq 3|gsed '2c1.5'
    1
    1.5
    3
    $ seq 3|sed '2s/.*/1.5/'
    1
    1.5
    3
    

    替代方案使用 awk

    $ seq 3|awk 'NR==2{print 1.5}1'
    1
    1.5
    2
    3
    $ seq 3|awk '{print NR==2?1.5:$0}'
    1
    1.5
    3
    

    awk 解释用 -v 传递的变量中的反斜杠,但不解释使用 ENVIRON 传递的变量:

    $ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
    1
    a
    3
    $ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
    1
    a\ba
    3
    

    ENVIRON-v 都由POSIX定义 .

  • 26

    OS X / macOS sed

    -i 标志在macOS sed 上的工作方式与GNU sed 不同 .

    以下是在macOS / OS X上使用它的方法:

    sed -i '' '8i\
    8 This is Line 8' FILE
    

    有关详细信息,请参阅 man 1 sed .

  • 11

    对于那些使用非GNU的SunOS的人,以下代码将有所帮助:

    sed '1i\^J
    line to add' test.dat > tmp.dat
    
    • ^ J插入^ V ^ J

    • 在'1i之后添加换行符 .

    • \必须是该行的最后一个字符 .

    • 命令的第二部分必须在第二行 .

  • 14

    Perl解决方案:

    快速又脏:

    perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

    • -l 剥离换行符并将其重新添加,无需"\n"

    • -p 循环输入文件,打印每一行

    • -e 用单引号执行代码

    $. 是行号

    相当于@glenn的awk解决方案,使用命名参数:

    perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

    • -s 启用了一个基本的参数解析器

    • -- 阻止-n和-s被标准的perl参数解析器解析

    位置命令参数:

    perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

    环境变量:

    setenv n 8 ; setenv s "Project_Name=sowstest"
    echo $n ; echo $s
    perl -slpe 'print $ENV{s} if $. == $ENV{n}' file
    

    ENV 是包含所有环境变量的哈希

    Getopt将参数解析为hash%o:

    perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

    Getopt ::长和长的选项名称

    perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

    Getopt是推荐的标准库解决方案 .
    这对于单行perl脚本来说可能有点过头了,但是可以做到

  • 15

    sed -e '8iProject_Name=sowstest' -i start 使用GNU sed

    样品运行:

    [root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
    [root@node23 ~]# cat a_file
    Line #1
    Line #2
    Line #3
    Line #4
    Line #5
    Line #6
    Line #7
    Line #8
    Line #9
    Line #10
    [root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
    [root@node23 ~]# cat -An a_file 
         1  Line #1$
         2  Line #2$
         3  xxx inserted line xxx$
         4  Line #3$
         5  Line #4$
         6  Line #5$
         7  Line #6$
         8  Line #7$
         9  Line #8$
        10  Line #9$
        11  Line #10$
    [root@node23 ~]# 
    [root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
    [root@node23 ~]# cat -n a_file 
         1  Line #1
         2  Line #2
         3  xxx inserted line xxx
         4  Line #3
         5  xxx (inserted) "line" xxx
         6  Line #4
         7  Line #5
         8  Line #6
         9  Line #7
        10  Line #8
        11  Line #9
        12  Line #10
    [root@node23 ~]#
    

相关问题