如何将一个文件的内容插入到另一个文件的模式(标记)之前?

如何将一个文件的内容插入到另一个文件的模式(标记)之前?

File1内容:

line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 

File2内容:

line1-file2     "25"  
line2-file2     "24"  
Pointer-file2   "23"  
line4-file2     "22" 
line5-file2     "21"

perl/shell脚本执行后,File2内容应变为:

line1-file2     "25"  
line2-file2     "24" 
line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 
Pointer-file2   "23" 
line4-file2     "22" 
line5-file2     "21"

File1即,将in的内容粘贴到File2包含“Pointer”的行之前。

答案1

sed实用程序有一个功能,可以就地进行修改:

sed -i -e '/Pointer/r file1' file2

但这让你指针内容上方的行file1。简单来说就是延迟线输出:

sed -n -i -e '/Pointer/r file1' -e 1x -e '2,${x;p}' -e '${x;p}' file2 

使用 GNU sed

sed '/Pointer/e cat file1' file2

根据手动的为了e [command]

请注意,与 r 命令不同,该命令的输出将立即打印; r 命令将输出延迟到当前周期结束。

答案2

不使用sedawk.

首先,找到您的图案所在的行:

line=$(grep -n 'Pointer' file2 | cut -d ":" -f 1)

然后,使用3个命令输出想要的结果:

{ head -n $(($line-1)) file2; cat file1; tail -n +$line file2; } > new_file

这有访问 3 次的缺点file2,但可能比 asedawk解决方案更清晰。

答案3

awk让这变得相当容易。
在文件前插入以下行:

awk '/Pointer/{while(getline line<"innerfile"){print line}} //' outerfile >tmp
mv tmp outerfile

要使内部文件在该Pointer行之后打印,只需切换模式的顺序(您需要添加分号以获得默认操作),然后可以删除变量line

awk '//; /Pointer/{while(getline<"innerfile"){print}}' outerfile >tmp
mv tmp outerfile

正因为还没有人用过perl

# insert file before line
perl -e 'while(<>){if($_=~/Pointer/){system("cat innerfile")};print}' outerfile

# after line
perl -e 'while(<>){print;if($_=~/Pointer/){system("cat innerfile")}}' outerfile

答案4

一项简单的工作ed

ed -s file1 <<IN
/Pointer/-r file2
,p
q
IN

-r file1将指定文件读入指定行之后,在本例中,该行是匹配 的第一行之前的行Pointer。因此file2,即使Pointer出现在多行中,这也只会插入一次内容。如果你想在每个匹配行之前插入它,请添加global 标志:

ed -s file1 <<IN
g/Pointer/-r file2
,p
q
IN

如果您想就地编辑文件,请替换,p为。w


接受的sed答案确实适用于大多数情况,但如果标记位于最后一行,则该命令将无法按预期工作:它将File1在标记之后插入 的内容。
我最初尝试过:

sed '/Pointer/{r file1
N}' file2

它也可以正常工作(就像r在循环结束时发挥其魔力一样),但如果标记位于最后一行(N最后一行之后没有分行),则会出现相同的问题。要解决这个问题,您可以在输入中添加换行符:

sed '/Pointer/{              # like the first one, but this time even if the
r file1                      # marker is on the last line in File2 it
N                            # will be on the second to last line in
}                            # the combined input so N will always work;
${                           # on the last line of input: if the line is
/^$/!{                       # not empty, it means the marker was on the last
s/\n$//                      # line in File2 so the final empty line in the
}                            # input was pulled i\n: remove the latter;
//d                          # if the line is empty, delete it
}' file2 <(printf %s\\n)

这将file2在每个匹配行之前插入内容。要仅在第一个匹配行之前插入它,您可以使用loop 并拉入next 行,直到到达文件末尾:

sed '/Pointer/{
r file2
N
:l
$!n
$!bl
}
${
/^$/!{
s/\n$//
}
//d
}' file1 <(printf %s\\n)

使用这些sed解决方案,您将失去就地编辑的能力(但您可以重定向到另一个文件)。

相关内容