I would like to use sed
(I think?) to replace a pattern with file contents.
我想用sed(我认为?)来替换带有文件内容的模式。
Example
File 1 (primary file)
Hello <<CODE>>
Goodbye.
File 2 (contents)
Anonymous person,
I am very nice.
File 3 (target)
Hello Anonymous person,
I am very nice.
Goodbye.
Right now, I am using this command:
现在,我正在使用以下命令:
sed "/<<CODE>>/{r file2
:a;n;ba}" file1 | \
sed "s/<<CODE>>//g" > \
file3
But this outputs:
但这输出:
Hello
Anonymous person,
I am very nice.
Goodbye.
(note the newline after Hello
)
(在Hello之后注意换行)
- How can I do this without getting that newline?
- (note that
file2
may contain all sorts of things: brackets, newlines, quotes, ...) - (注意文件2可能包含各种东西:括号、换行符、引号……)
- (note that
- 我怎么能在没有换行符的情况下做到这一点呢?(注意文件2可能包含各种东西:括号、换行符、引号……)
5 个解决方案
#1
2
Much simpler to use awk:
使用awk要简单得多:
awk 'FNR==NR{s=(!s)?$0:s RS $0;next} /<<CODE>>/{sub(/<<CODE>>/, s)} 1' file2 file1
Hello Anonymous person,
I am very nice.
Goodbye.
Explanation:
解释:
-
FNR==NR
- Execute this block for first file in input i.e.file2
- FNR==NR -为输入的第一个文件(即file2)执行此块
-
s=(!s)?$0:s RS $0
- Concatenate whole file content in strings
- s =(!)?$0:s RS $0 -在字符串s中连接整个文件内容
-
next
- Read next line untilEOF
on first file - 接下来——读下一行直到第一个文件上的EOF
-
/<<CODE>>/
- If a line with<<CODE>>
is found execute that block -
/< CODE>>/ -如果找到
>的行,执行该块
-
sub(/<<CODE>>/, s)
- Replace<<CODE>>
with strings
(data offile2
) -
sub(/< CODE>>/, s) -将<
>替换为string s (file2数据)
-
1
- print the output - 1 -打印输出。
EDIT: Non-regex way:
编辑:Non-regex道:
awk 'FNR==NR{s=(!s)?$0:s RS $0; next}
i=index($0, "<<CODE>>"){$0=substr($0, 1, i-1) s substr($0, i+8)} 1' file2 file1
#2
1
The awk
though it might be harder to read, is probably the right way to go.
awk虽然可能比较难读,但可能是正确的选择。
Just for comparison sake, here's a ruby version
为了便于比较,这里有一个ruby版本
ruby -ne 'BEGIN{@body=File.open("file2").read}; puts gsub(/<<CODE>>/,@body);' < file1
#3
0
I am thinking about a solution where we use Bash to evaluate a cat
process outside of the single quotes delimitating the sed
script, but unfortunately the following doesn't work as soon as your file2
contains a newline:
我正在考虑一种解决方案,我们使用Bash来评估除分隔sed脚本的单引号之外的cat进程,但不幸的是,一旦file2包含了换行符,以下内容就不能工作:
sed 's/<<CODE>>/'"$(cat file2)"'/' file1
It accepts spaces in file2
, but not newlines, as you can see in the following piece of code that works well, whatever the content of file2
:
它接受file2中的空格,但不接受换行,正如您在以下代码片段中看到的那样,无论file2的内容是什么,它都工作得很好:
sed 's/<<CODE>>/'"$(cat file2 | tr -d '\n')"'/' file1
But, obviously, this modifies the content of the file before inclusion, which is simply bad. :-(
但是,显然,这在包含之前修改了文件的内容,这是很糟糕的。:-(
So if you want to play, you can first tr
the newlines to some weird unexpectable character, and translate those back after sed
has worked on its script:
所以,如果你想玩,你可以先把换行符转换成一些不可预知的奇怪角色,然后在sed完成脚本之后再把它们翻译回来:
sed 's/<<CODE>>/'"$(cat file2 | tr '\n' '\3')"'/' file1 | tr '\3' '\n'
#4
0
not too bad in Perl
:
在Perl中还不错:
cat file1 | perl -e "open FH, qq(file2); \$f2=join '', <FH>; chomp \$f2; map {s/<<CODE>>/\$f2/g; print \$_} <STDIN>" > file3
(maybe i am not the best perl coder)
(也许我不是最好的perl程序员)
it's straight-forward. read the whole file2 in, substitute it, then print.
这是直接的。读取整个file2,替换它,然后打印。
#5
0
You could do simply with:
你只需要:
awk '{gsub("<<CODE>>", filetwo)}1' filetwo="$(<file2)" file1
#1
2
Much simpler to use awk:
使用awk要简单得多:
awk 'FNR==NR{s=(!s)?$0:s RS $0;next} /<<CODE>>/{sub(/<<CODE>>/, s)} 1' file2 file1
Hello Anonymous person,
I am very nice.
Goodbye.
Explanation:
解释:
-
FNR==NR
- Execute this block for first file in input i.e.file2
- FNR==NR -为输入的第一个文件(即file2)执行此块
-
s=(!s)?$0:s RS $0
- Concatenate whole file content in strings
- s =(!)?$0:s RS $0 -在字符串s中连接整个文件内容
-
next
- Read next line untilEOF
on first file - 接下来——读下一行直到第一个文件上的EOF
-
/<<CODE>>/
- If a line with<<CODE>>
is found execute that block -
/< CODE>>/ -如果找到
>的行,执行该块
-
sub(/<<CODE>>/, s)
- Replace<<CODE>>
with strings
(data offile2
) -
sub(/< CODE>>/, s) -将<
>替换为string s (file2数据)
-
1
- print the output - 1 -打印输出。
EDIT: Non-regex way:
编辑:Non-regex道:
awk 'FNR==NR{s=(!s)?$0:s RS $0; next}
i=index($0, "<<CODE>>"){$0=substr($0, 1, i-1) s substr($0, i+8)} 1' file2 file1
#2
1
The awk
though it might be harder to read, is probably the right way to go.
awk虽然可能比较难读,但可能是正确的选择。
Just for comparison sake, here's a ruby version
为了便于比较,这里有一个ruby版本
ruby -ne 'BEGIN{@body=File.open("file2").read}; puts gsub(/<<CODE>>/,@body);' < file1
#3
0
I am thinking about a solution where we use Bash to evaluate a cat
process outside of the single quotes delimitating the sed
script, but unfortunately the following doesn't work as soon as your file2
contains a newline:
我正在考虑一种解决方案,我们使用Bash来评估除分隔sed脚本的单引号之外的cat进程,但不幸的是,一旦file2包含了换行符,以下内容就不能工作:
sed 's/<<CODE>>/'"$(cat file2)"'/' file1
It accepts spaces in file2
, but not newlines, as you can see in the following piece of code that works well, whatever the content of file2
:
它接受file2中的空格,但不接受换行,正如您在以下代码片段中看到的那样,无论file2的内容是什么,它都工作得很好:
sed 's/<<CODE>>/'"$(cat file2 | tr -d '\n')"'/' file1
But, obviously, this modifies the content of the file before inclusion, which is simply bad. :-(
但是,显然,这在包含之前修改了文件的内容,这是很糟糕的。:-(
So if you want to play, you can first tr
the newlines to some weird unexpectable character, and translate those back after sed
has worked on its script:
所以,如果你想玩,你可以先把换行符转换成一些不可预知的奇怪角色,然后在sed完成脚本之后再把它们翻译回来:
sed 's/<<CODE>>/'"$(cat file2 | tr '\n' '\3')"'/' file1 | tr '\3' '\n'
#4
0
not too bad in Perl
:
在Perl中还不错:
cat file1 | perl -e "open FH, qq(file2); \$f2=join '', <FH>; chomp \$f2; map {s/<<CODE>>/\$f2/g; print \$_} <STDIN>" > file3
(maybe i am not the best perl coder)
(也许我不是最好的perl程序员)
it's straight-forward. read the whole file2 in, substitute it, then print.
这是直接的。读取整个file2,替换它,然后打印。
#5
0
You could do simply with:
你只需要:
awk '{gsub("<<CODE>>", filetwo)}1' filetwo="$(<file2)" file1