【问题标题】:Merging of two files with substitution用替换合并两个文件
【发布时间】:2022-01-12 14:43:38
【问题描述】:

我需要合并两个文件,将文件 2 的包含直接添加到文件 1 的末尾。值得注意的是第一个文件的最后一行包含短语“END”。我需要删除它并在那里添加文件 2 的内容:

文件 1:

string 1
string 2
string N
END

文件 2:

string 3
string 4
string M

应该给我文件 3

string 1
string 2
string N
string 3
string 4
string M

我试过简单地使用

cat file1 file2 >> file3

但它没有替换 file2 中的 END。我可以为此使用特殊选项吗?

【问题讨论】:

  • 第一个文件是否总是以END 作为最后一行?如果是这样,您可以使用cat <(head -n -1 file1) file2
  • 是的,第一个文件中总是有 END,它就像一个模式,应该被文件 2 的内容识别和替换。我已经厌倦了我们的解决方案,但它只打印给我文件2的内容,所以..

标签: bash awk sed cat tac


【解决方案1】:

使用sed:

sed -e '${r file2' -e ';$d;}' file1

string 1
string 2
string N
string 3
string 4
string M

如果你想直接使用shell 变量而不是文件名:

sed -i.bak -e "\${r $f2" -e ';$d;}' "$f1"

【讨论】:

  • 谢谢!是否可以直接在文件 1 中进行此类修改,而无需使用 sed -e '${r file2' -e ';$d;}' file1 >> file3 创建新文件
  • @HotJAMS 取决于您的sed 版本,但通常您可以使用sed -i /^END$/d file1,它会删除包含END 的行; IIUC,这就是你要找的。​​span>
  • @HotJAMS:您可以使用:sed -i.bak -e '${r file2' -e ';$d;}' file1 将更改保存到file1
  • 如果我在我的 bash 脚本中使用这个 sed,我可以在 sed 中使用一个 bash 变量来指示文件 2 和 file1 的路径吗? sed -i.bak -e '${r "${path_defined_in_my_bash_script}"/file1.pdb' -e ';$d;}' "${path_defined_in_my_bash_script2}"/file2.pqr
  • 好的,谢谢!与下面提到的 awk 解决方案相比,它不能直接在 bash 环境中工作,其中文件 1 和文件 2 可以直接定义为变量..
【解决方案2】:

awk 的方法。它只是!跳过file1 的最后一行发生的ENDs。它通过使用辅助变量set 识别file1 的最后一行。

file中使用多个END进行测试

% awk 'set==""&&NR!=FNR&&last=="END"{last="";set=1} 
    last!=""{print last} 
    {last=$0} END{print}' file file
string 1
string 2
END
string N
string 1
string 2
END
string N
END

使用file1file2

% awk 'set==""&&NR!=FNR&&last=="END"{last="";set=1} 
    last!=""{print last} 
    {last=$0} END{print}' file1 file2
string 1
string 2
string N
string 3
string 4
string M

数据

% cat file
string 1
string 2
END
string N
END

% cat file1
string 1
string 2
string N
END

% cat file2
string 3
string 4
string M

【讨论】:

  • 我认为 OP 想从 file1 中删除最后一行,而不仅仅是带有 END 值的行
  • @anubhava 嗯,谢谢,会调整的。
【解决方案3】:

这可能对你有用(GNU head & cat):

head -n-1 file1 | cat - file2 > file3

读取 file1 的最后一行以外的所有内容,并将其与 file2 连接。

另一种选择:

sed -i -e '$r file2' -e '$d' file1

这会将file2附加到file1的末尾减去file1的最后一行,然后用结果替换file1。

【讨论】:

    【解决方案4】:

    在此处添加 1 个tac + awk 解决方案的变体以获得乐趣。

    tac file1 | awk 'FNR==1{system("tac file2");next} 1' | tac
    

    说明:为上述添加详细说明。

    tac file1 |               ##using tac command to read contents from bottom to up and sending its standard output as standard input to awk command here.
    awk '                     ##Starting awk program from here.
      FNR==1{                 ##Checking condition if this is first line then do following.
        system("tac file2")   ##Printing file2 bottom to up contents.
        next                  ##next will skip all further contents from here.
      }
      1                       ##Printing rest of lines(passed from tac file1) here.
    ' | tac                   ##Reversing order again to make it into original order.
    

    【讨论】:

      【解决方案5】:

      假设:

      • file1 只有一个标记为 END 的条目
      • END 条目位于file1 的末尾

      对 OP 当前的 cat 想法进行小修改,使用进程替换从 file1 中删除 END

      $ cat <(grep -v '^END$' file1) file2 > file3
      $ cat file3
      string 1
      string 2
      string N
      string 3
      string 4
      string M
      

      Andre 的awk 解决方案的一种变体,我们打印我们看到的所有内容除了file1/END 条目:

      $ awk 'FNR==NR && /^END$/ {next} 1' file1 file2 > file3
      $ cat file3
      string 1
      string 2
      string N
      string 3
      string 4
      string M
      

      【讨论】:

        猜你喜欢
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 2019-04-28
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 2020-06-16
        • 1970-01-01
        相关资源
        最近更新 更多