用文件的内容替换某些标记(使用 bash 脚本)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4379207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:03:25  来源:igfitidea点击:

Replace certain token with the content of a file (using a bash-script)

bashsedawkreplace

提问by aioobe

I have a file containing some text and the words INSERT_HERE1and INSERT_HERE2. I'd like to replace these words with the content of file1.txtand file2.txtrespectively.

我有一个包含一些文本和单词INSERT_HERE1和的文件INSERT_HERE2。我想要的内容替换这些词file1.txtfile2.txt分别。

I suspect sedor awkcould pull it off but I've basically never used them.

我怀疑sedawk可以实现它,但我基本上从未使用过它们。

采纳答案by codaddict

If you are okay with Perl you can do:

如果你对 Perl 没问题,你可以这样做:

$ cat FILE1
this is file1

$ cat FILE2
this is file2

$ cat file
foo
INSERT_HERE1
bar
INSERT_HERE2
baz

$ perl -ne 's/^INSERT_HERE(\d+)\s+$/`cat FILE`/e;print' file
foo
this is file1
bar
this is file2
baz
$ 

回答by MattoxBeckman

Sed does have a built-in read file command. The commands you want would look something like this:

Sed 确实有一个内置的读取文件命令。你想要的命令看起来像这样:

$ sed -e '/INSERT_HERE1/ {
r FILE1
d }' -e '/INSERT_HERE2/ {
r FILE2
d }' < file

This would output

这将输出

foo
this is file1
bar
this is file2
baz

The r command reads the file, and the d command deletes the line with the INSERT_HEREtags. You need to use the curly braces since sed commands and multi-line input since sed commands have to start on their own line, and depending on your shell, you may need \at the end of the lines to avoid premature execution. If this is something you would use a lot, you can just put the command in a file and use sed -fto run it.

r 命令读取文件,d 命令删除带有INSERT_HERE标签的行。您需要使用大括号,因为 sed 命令和多行输入,因为 sed 命令必须从它们自己的行开始,并且根据您的 shell,您可能需要\在行的末尾以避免过早执行。如果这是你sed -f经常使用的东西,你可以把命令放在一个文件中并用来运行它。

回答by Paused until further notice.

This is suitable for small substitution files that may be substituted many times:

这适用于可能被多次替换的小替换文件:

awk 'BEGIN {
        while ((getline line < ARGV[1]) > 0) {file1 = file1 nl line; nl = "\n"}; 
        close (ARGV[1]); nl = "";
        while ((getline line < ARGV[2]) > 0) {file2 = file2 nl line; nl = "\n"};
        close (ARGV[2]);
        ARGV[1] = ""; ARGV[2] = "" }
      { gsub("token1", file1); 
        gsub("token2", file2); 
        print }' file1.txt file2.txt mainfile.txt

You may want to add some extra newlines here and there, depending on how you want your output to look.

您可能希望在这里和那里添加一些额外的换行符,具体取决于您希望输出的外观。

回答by SiegeX

Easily done with Bash. If you need it to be POSIX shell let me know:

使用 Bash 轻松完成。如果您需要它是 POSIX shell,请告诉我:

#!/bin/bash

IFS=  # Needed to prevent the shell from interpreting the newlines
f1=$(< /path/to/file1.txt)
f2=$(< /path/to/file2.txt)

while read line; do 
  if [[ "$line" == "INSERT_HERE1" ]]; then
     echo "$f1"
  elif [[ "$line" == "INSERT_HERE2" ]]; then
     echo "$f2"
  else
     echo "$line"
  fi
done < /path/to/input/file

回答by Jonathan

This is not tested, but would be pretty close to what you need:

这未经测试,但非常接近您的需要:

sed -e "s/INSERT_HERE1/`cat file1.txt`/" -e "s/INSERT_HERE2/`cat file2.txt`/" <file >file.out

It will not properly handle a file with slashes in it, though, so you may need to tweak it a bit.

但是,它无法正确处理带有斜杠的文件,因此您可能需要稍微调整一下。

I'd recommend Perl instead, though. Something like this:

不过,我更推荐 Perl。像这样的东西:

#!/usr/bin/perl -w

my $f1 = `cat file1.txt`;
my $f2 = `cat file2.txt`;

while (<>) {
    chomp;
    s/INSERT_HERE1/$f1/;
    s/INSERT_HERE2/$f2/;
    print "$_\n";
}

This assumes that INSERT_HERE1 and INSERT_HERE2 may only appear once per line, and that the file1.txtdoes not include the text INSERT_HERE2 (wouldn't be difficult to fix, though). Use like this:

这假设 INSERT_HERE1 和 INSERT_HERE2 每行只能出现一次,并且file1.txt不包括文本 INSERT_HERE2(虽然不难修复)。像这样使用:

./script <file >file.out

回答by dersimn

This snippet replaces any section that is specified in the upper array. For e.g. here

此代码段替换了上面数组中指定的任何部分。例如这里

<!--insert.txt-->

with the contents of "insert.txt"

带有“insert.txt”的内容

#!/bin/bash

replace[1]=\<!--insert.txt--\>      ; file[1]=insert.txt
replace[2]=\<!--insert2.txt--\>     ; file[2]=insert2.txt

replacelength=${#replace[@]}

cat blank.txt > tmp.txt
for i in $(seq 1 ${replacelength})
do
    echo Replacing ${file[i]} ...
    sed -e "/${replace[i]}/r ${file[i]}" -e "/${replace[i]}/d" tmp.txt > tmp_2.txt
    mv tmp_2.txt tmp.txt
done
mv tmp.txt file.txt

If you're not afraid of .zip files you can try this example as long as it is online: http://ablage.stabentheiner.de/2013-04-16_contentreplace.zip

如果你不害怕 .zip 文件,只要它在线,你可以试试这个例子:http: //ablage.stabentheiner.de/2013-04-16_contentreplace.zip

回答by Nicholas Sushkin

I would use perl's in place replacement with -i.extoption

我会用-i.ext选项使用 perl 的就地替换

perl -pi.bak -e 's|INSERT_HERE1|`cat FILE1`|ge; 
                 s|INSERT_HERE2|`cat FILE2`|ge;' myfile

Then, use diff myfile.bak myfileto verify:

然后,使用diff myfile.bak myfile验证: