在另一个多行文本文件中查找并替换一个多行文本文件

在另一个多行文本文件中查找并替换一个多行文本文件

我与它斗争了很长时间,但现在我完全没有想法了。也许这里有人能帮助我。这是我想要实现的目标:

file_1.txt

# Some comment
some_variable="test"
some other things

# Marker

More things!@#$%^

file_2.txt

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

我想插入file_2.txtfile_1.txt代替# Marker,稍后我想反转这个过程。

最终文件file_1.txt

# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

问题是,这两个文件都是多行的,并且包含各种特殊字符。我还想将这两个文件放在变量中。

我尝试了各种东西,sed、perl 和 awk。对我来说没有任何作用。我认为这是我最接近的尝试:

perl -pi -e 'chomp if eof' file_2.txt
marker_var="# Marker"
file_2_var=$(tr '\n' '\f' <file_2.txt)

sed -e "s|$marker_var|$file_2_var| tr '\f' '\n'" file_1.txt

我说最接近是因为它仍然不起作用。我尝试结合 stackexchange 的各种答案,但它会抛出有关未正确结束的错误s。我怀疑这是因为\n文件中的最后一个新行,所以我尝试使用 perl 命令删除它,但它不起作用。

有人可以帮帮我吗?

答案1

如果你已经有了 perl,那么就一直执行 perl:

open(f1,"<file_1.txt");
open(f2,"<file_2.txt");
open(out,">new_file_1.txt");

while(<f1>) {
   last if /# Marker/;
   print out;
}
print out while(<f2>);
print out while(<f1>);

close(out);
close(f1);
close(f2);

答案2

使用 awk 合并文件实际上很简单:

awk 'NR==FNR {if ($1 == "#" && $2 == "Marker") while((getline a<ARGV[2]) > 0) print a; else print}' file_1.txt file_2.txt > out
  • NR==FNR这是一个 awk 技巧,用于确保我们只对第一个文件进行操作。检查这个回答以获取更多信息关于 NR 和 FNR
  • {if ($1 == "#" && $2 == "Marker")else print}# Marker:解析第一个文件并输出所有行不是成立。
  • while((getline a<ARGV[2]) > 0) print a;解析ARGV[2]的内容(这里是file_2.txt)并输出。
  • > out是一个 shell 重定向,并将此命令的输出写入 out 文件中(如果该文件不存在,则创建该文件。

结果 :

$ awk 'NR==FNR {if ($1 == "#" && $2 == "Marker") while((getline a<ARGV[2]) > 0) print a; else print}' file_1.txt file_2.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

答案3

使用sed

$ sed -Ee '/Marker/{e cat file_2.txt' -e ';d}' file_1.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"


More things!@#$%^

答案4

使用任何 awk:

$ awk 'NR==FNR{new=new sep $0; sep=ORS; next} /# Marker/{$0=new} 1' file_2.txt file_1.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

$ awk 'NR==FNR{new=new sep $0; sep=ORS; next} /# Marker/{$0=new} 1' file_1.txt file_2.txt
# Some comment
some_variable="test"
some other things

# Marker

More things!@#$%^
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

关于您问题中的脚本:

  1. 一旦您这样做,tr '\n' '\f'您就不再拥有有效的文本文件,因为它不再包含所需的终止换行符,因此 YMMVsed或任何其他文本处理工具将对其进行处理。
  2. 当您的输入包含换页符时,将换行符映射到换页符的过程将会失败,就像在代码中的函数之间使用的那样,希望在打印时强制函数从新页面的顶部开始(或其他类似的文本)打印时需要在特定位置分页)。
  3. 你不能这样做,sed -e "s|$marker_var|$file_2_var|因为file_2_var它本身可能包含|s 或反向引用,例如&sed\1然后会解释,请参阅https://stackoverflow.com/q/29613304/1745001

相关内容