将一个文件的内容插入到另一个文件中(在发送的文件的特定行中)-BASH/LINUX

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14044032/
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-18 04:05:29  来源:igfitidea点击:

insert the contents of a file to another (in a specific line of the file that is sent)-BASH/LINUX

linuxbashshell

提问by Jonathan Leffler

I tried doing it with catand then after I type the second file I added | head -$line | tail -1but it doesn't work because it performs catfirst.

我尝试这样做cat,然后在我输入我添加的第二个文件后,| head -$line | tail -1但它不起作用,因为它cat首先执行。

Any ideas? I need to do it with cator something else.

有任何想法吗?我需要用它cat或别的东西来做。

回答by Jonathan Leffler

I'd probably use sedfor this job:

我可能会sed用于这项工作:

line=3
sed -e "${line}r file2" file1

If you're looking to overwrite file1and you have GNU sed, add the -ioption. Otherwise, write to a temporary file and then copy/move the temporary file over the original, cleaning up as necessary (that's the trapstuff below). Note: copying the temporary over the file preserves links; moving does not (but is swifter, especially if the file is big).

如果您想覆盖file1并且您有 GNU sed,请添加该-i选项。否则,写入一个临时文件,然后将临时文件复制/移动到原始文件上,根据需要进行清理(这就是trap下面的内容)。注意:在文件上复制临时文件会保留链接;移动没有(但更快,特别是如果文件很大)。

line=3
tmp="./sed.$$"
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
sed -e "${line}r file2" file1 > $tmp
cp $tmp file1
rm -f $tmp
trap 0

回答by gniourf_gniourf

Just for fun, and just because we all love ed, the standard editor, here's an edversion. It's very efficient (edis a genuinetext editor)!

只是为了好玩,也只是因为我们都喜欢ed标准编辑器,这里有一个ed版本。它非常高效(ed是一个真正的文本编辑器)!

ed -s file2 <<< $'3r file1\nw'

If the line number is stored in the variable linethen:

如果行号存储在变量中,line则:

ed -s file2 <<< "${line}r file1"$'\nw'

Just to please Zack, here's one version with less bashism, in case you don't like bash (personally, I don't like pipes and subshells, I prefer herestrings, but hey, as I said, that's only to please Zack):

只是为了取悦 Zack,这里有一个不那么 bashism 的版本,以防你不喜欢 bash(就个人而言,我不喜欢管道和子外壳,我更喜欢 herestrings,但是嘿,正如我所说,这只是为了取悦 Zack):

printf "%s\n" "${line}r file1" w | ed -s file2

or (to please Sorpigal):

或(为了取悦 Sorpigal):

printf "%dr %s\nw" "$line" file1 | ed -s file2

As Jonathan Leffler mentions in a comment, and if you intend to use this method in a script, use a heredoc (it's usually the most efficient):

正如 Jonathan Leffler 在评论中提到的,如果您打算在脚本中使用此方法,请使用 heredoc(它通常是最有效的):

ed -s file2 <<EOF
${line}r file1
w
EOF

Hope this helps!

希望这可以帮助!

P.S. Don't hesitate to leave a comment if you feel you need to express yourself about the ways to drive ed, the standard editor.

PS 如果您觉得需要表达自己的驾驶方式ed,标准编辑器,请不要犹豫,发表评论。

回答by sorpigal

Lots of ways to do it, but I like to to choose a way that involves making tools.

有很多方法可以做到,但我喜欢选择一种涉及制作工具的方法。

First, setup test environment

一、搭建测试环境

rm -rf /tmp/test
mkdir /tmp/test
printf '%s\n' {0..9} > /tmp/test/f1
printf '%s\n' {one,two,three,four,five,six,seven,eight,nine,ten} > /tmp/test/f2

Now let's make the tool, and in this first pass we'll implement it badly.

现在让我们制作工具,在这第一遍中,我们将错误地实现它。

# insert contents of file  into file  at line 
insert_at () { insert="" ; into="" ; at="" ; { head -n $at "$into" ; ((at++)) ; cat "$insert" ; tail -n +$at "$into" ; } ; }

Then run the tool to see the amazing results.

然后运行该工具以查看惊人的结果。

$ insert_at /tmp/test/f1 /tmp/test/f2 5

But wait, the result is on stdout! What about overwriting the original? No problem, we can make another tool for that.

但是等等,结果在标准输出上!覆盖原来的怎么办?没问题,我们可以为此制作另一个工具。

insert_at_replace () { tmp=$(mktemp) ; insert_at "$@" > "$tmp" ; mv "$tmp" "" ; }

And run it

并运行它

$ insert_at_replace /tmp/test/f1 /tmp/test/f2 5
$ cat /tmp/test/f2

"Your implementation sucks!"

“你的实施很糟糕!”

I know, but that's the beauty of making simple tools. Let's replace insert_atwith the sed version.

我知道,但这就是制作简单工具的美妙之处。让我们替换insert_at为 sed 版本。

insert_at () { insert="" ; into="" ; at="" ; sed -e "${at}r ${insert}" "$into" ; }

And insert_at_replacekeeps working (of course). The implementation of insert_at_replacecan also be changed to be less buggy, but I'll leave that as an exercise for the reader.

insert_at_replace继续工作(当然)。的实施insert_at_replace也可以改为车少,但我会离开,作为一个练习留给读者。

回答by techno

cat file1 >>file2

will append content of file1 to file2.

将文件 1 的内容附加到文件 2。

cat file1 file2

will concatenate file1 and file2 and send output to terminal.

将连接 file1 和 file2 并将输出发送到终端。

cat file1 file2 >file3

will create or overwite file3 with concatenation of file1 and file2

将通过连接 file1 和 file2 创建或覆盖 file3

cat file1 file2 >>file3

will append concatenation of file1 and file2 to end of file3.

将文件 1 和文件 2 的连接追加到文件 3 的末尾。

Edit:

编辑

For trunking file2 before adding file1:

在添加文件 1 之前中继文件 2:

sed -e '11,$d' -i file2 && cat file1 >>file2

or for making a 500 lines file:

或者制作一个 500 行的文件:

n=$((500-$(wc -l <file1)))
sed -e "1,${n}d" -i file2 && cat file1 >>file2

回答by combinatorist

I like doing this with headand tailif you don't mind managing a new file:

我喜欢这样做,head而且tail如果你不介意管理的新文件:

head -n 16 file1 >  file3 &&
cat        file2 >> file3 &&
tail -n+56 file1 >> file3

You can collapse this onto one line if you like. Then, if you really need it to overwrite file1, do: mv file3 file1(optionally include &&between commands).

如果您愿意,可以将其折叠到一行中。然后,如果您确实需要它来覆盖 file1,请执行以下操作mv file3 file1:(可选地&&在命令之间包含)。

Notes:

笔记:

  • head -n 16 file1means first 16 lines of file1
  • tail -n+56 file1means file1 starting from line 56 to the end
  • Hence, I actually skipped lines 17 through 55 from file1.
  • Of course, if you could change 56 to 17 so no lines are skipped.
  • I prefer to mix simple headand tailcommands then try a magic sedcommand.
  • head -n 16 file1表示 file1 的前 16 行
  • tail -n+56 file1表示从第 56 行开始到末尾的 file1
  • 因此,我实际上从文件 1 中跳过了第 17 行到第 55 行。
  • 当然,如果您可以将 56 更改为 17,则不会跳过任何行。
  • 我更喜欢混合简单headtail命令,然后尝试使用魔术sed命令。