Sed用文件内容替换模式

时间:2022-03-05 22:04:55

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可能包含各种东西:括号、换行符、引号……)
  • 我怎么能在没有换行符的情况下做到这一点呢?(注意文件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 string s
  • s =(!)?$0:s RS $0 -在字符串s中连接整个文件内容
  • next - Read next line until EOF on first file
  • 接下来——读下一行直到第一个文件上的EOF
  • /<<CODE>>/ - If a line with <<CODE>> is found execute that block
  • /< CODE>>/ -如果找到>的行,执行该块
  • sub(/<<CODE>>/, s) - Replace <<CODE>> with string s (data of file2)
  • 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 string s
  • s =(!)?$0:s RS $0 -在字符串s中连接整个文件内容
  • next - Read next line until EOF on first file
  • 接下来——读下一行直到第一个文件上的EOF
  • /<<CODE>>/ - If a line with <<CODE>> is found execute that block
  • /< CODE>>/ -如果找到>的行,执行该块
  • sub(/<<CODE>>/, s) - Replace <<CODE>> with string s (data of file2)
  • 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

相关文章