Linux Bash:插入一个文件&x27;将内容插入模式后的另一个文件中

Linux Bash:插入一个文件&x27;将内容插入模式后的另一个文件中,linux,bash,shell,sh,Linux,Bash,Shell,Sh,我正在尝试编写一个bash脚本,它将执行以下操作: 从第一个文件读取内容(作为第一个参数) 从第二个文件读取内容(作为第二个参数) 在第二个文件中查找具有给定模式的行(作为第三个参数) 将文本从第一个文件插入到图案行后的第二个文件中 在屏幕上打印最终文件 例如: 第一个文件.txt: 111111 1111 11 1 122221 2222 22 2 第二个_file.txt: 111111 1111 11 1 122221 2222 22 2 模式: 2222 输出: 122221

我正在尝试编写一个bash脚本,它将执行以下操作:

  • 从第一个文件读取内容(作为第一个参数)
  • 从第二个文件读取内容(作为第二个参数)
  • 在第二个文件中查找具有给定模式的行(作为第三个参数)
  • 将文本从第一个文件插入到图案行后的第二个文件中
  • 在屏幕上打印最终文件
  • 例如:

    第一个文件.txt:

    111111
    1111
    11
    1
    
    122221
    2222
    22
    2
    
    第二个_file.txt:

    111111
    1111
    11
    1
    
    122221
    2222
    22
    2
    
    模式:

    2222
    
    输出:

    122221
    111111
    1111
    11
    1
    2222
    111111
    1111
    11
    1
    22
    2
    
    我应该用什么在BASH上实现这个功能

    我写了代码,但它不能正常工作(为什么?)

    #/bin/bash
    第一个文件名=“$1”
    第二个文件名=“$2”
    pattern=“$3”
    而read-r行
    做
    如果[[$line=]$$pattern]];然后
    当读取-r行2时
    做
    echo$line2
    完成<$second\u文件名
    fi
    回音$线
    完成<$first\u文件名
    
    sed
    可以在没有循环的情况下完成。使用其
    r
    命令:

    sed -e '/pattern/rFILE1' FILE2
    
    测试会话:

    $ cd -- "$(mktemp -d)" 
    $ printf '%s\n' 'nuts' 'bolts' > first_file.txt
    $ printf '%s\n' 'foo' 'bar' 'baz' > second_file.txt
    $ sed -e '/bar/r./first_file.txt' second_file.txt
    foo
    bar
    nuts
    bolts
    baz
    

    =~
    运算符周围需要空格。比较:

    [[ foo=~bar ]]
    [[ foo =~ bar ]]
    
    这是因为第一个表达式的计算结果本质上是“ThisString为空吗?”

    此外,操作代码使用而不是

    即使如此,您也可以轻松摆脱内部循环。只需将整个
    while read-r line2
    位替换为
    cat--“$second\u filename”

    只有当文件未以换行符结尾时,您的最后一个
    echo$line
    才是正确的(标准的*nix工具)。相反,您应该在读取-r行| |[[$line~='']]时使用
    。这适用于末尾有或没有换行符的情况

    此外,.

    这应该可以:

    perl -lne 'BEGIN{open(A,"first_file.txt");@f=<A>;}print;if(/2222/){print @f}' second_file.txt
    
    perl-lne'开始{open(A,“first_file.txt”);@f=}打印;如果(/2222/){print@f}'second_file.txt
    
    测试:

    > cat temp
    111111
    1111
    11
    1
    > cat temp2
    122221
    2222
    22
    2
    > perl -lne 'BEGIN{open(A,"temp");@f=<A>;}print;if(/2222/){print @f}' temp2
    122221
    111111
    1111
    11
    1
    
    2222
    111111
    1111
    11
    1
    
    22
    2
    > 
    
    >cat温度
    111111
    1111
    11
    1.
    >cat temp2
    122221
    2222
    22
    2.
    >perl-lne'BEGIN{open(A,“temp”);@f=;}print;如果(/2222/){print@f}'temp2
    122221
    111111
    1111
    11
    1.
    2222
    111111
    1111
    11
    1.
    22
    2.
    > 
    
    使用awk
    也可以

    要在#####标记###行之前插入,请执行以下操作:


    如果您希望在生产线内部进行更换(仅更换模式并保留生产线的其余部分),则可以使用sed而不是awk,实现类似的解决方案。我这样使用sed,它很有魅力

    sed-i-e'/pattern/r filetoinsert'filetobeinserted

    它所做的是在具有指定模式的行后面的“filetoinsert”中插入“filetobeinserted”


    注意选择一个独特的模式,不确定它将如何与重复的模式一起工作,我假设它只会在第一个模式中这样做

    对于第四个点,
    sed-I“line,text…”
    可以做到。你能举个小例子吗?(输入和预期输出)当前代码中发生了什么?“不起作用”不是一个很好的错误description@EmilVikstrom:我的代码只是在第二个文件名的每一行中输出第一个文件名的内容。不正确../replace_shell.sh:第9行:应为条件二进制运算符。/replace_shell.sh:第9行:
    =$]附近的语法错误。/replace_shell.sh:第9行:
    如果[[$line=$$pattern]];然后,当我尝试这样做:“cat--“$second_filename”:我得到了一个错误:sed:1:“file2.txt”“:无效的命令代码f@user2431907
    =$
    =~
    不同<代码>是。@user2431907
    sed
    ?原始代码中没有
    sed
    命令。如果需要帮助,最好发布实际代码。+1从未听说过
    r
    命令。添加了一个要验证的测试会话。是否有办法确保它只插入一次?@l0b0
    sed-e'1,/pattern/rFILE1'FILE2
    将只插入一次,但在第一行出现了一个边缘情况。在这种情况下,使用GNU sed:
    sed'0,/pattern/rFILE1'FILE2
    @l0b0@potong:Or,使用分支:
    sed-e'/pattern/{r FILE1'-e'br'-e'-e'-b'-e':r{n;br'-e'-e'-2
    对于“只做一次”请求,有时
    ed
    ,虽然比sed更详细,但比sed:
    printf s\n'/2222/r first\r'-txt文件1更清晰,$p'q | ed second_file.txt 2>/dev/null
    --若要就地编辑,请将'1,$p'替换为'w'这是一种处理方式,当变量中有引号时,sed无法真正处理我的awk解决方案(替换标记):awk-v f=“$file”/#marker#marker##/{system(“cat”f);next};1'--其中要插入的文件$file的名称中不能有空格:/
    // for each <line> of second_file.txt :
    //   **without any condition :** print <line>
    //   if <line> matches regexp ###marker###, outputs first_file.txt.
    awk '{ print; } \
         /###marker###/ { system ( "cat first_file.txt" ) } \' second_file.txt
    
    // for each <line> of second_file.txt :
    //   if <line> matches regexp ###marker###, outputs first_file.txt.
    //   **else**, print <line>
    awk '/###marker###/ { system ( "cat first_file.txt" ) } \
         !/###marker###/ { print; }' second_file.txt
    
    > second_file.txt.new
    mv second_file.txt{.new,}
    // (like "mv second_file.txt.new second_file.txt", but shorter to type !)