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

问题描述 投票:0回答:5

我尝试使用

cat
执行此操作,然后在输入第二个文件后添加
| head -$line | tail -1
但它不起作用,因为它首先执行
cat

有什么想法吗?我需要用

cat
或其他东西来做。

linux bash shell
5个回答
25
投票

我可能会使用

sed
来完成这项工作:

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

如果您想要覆盖

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

10
投票

只是为了好玩,也因为我们都喜欢标准编辑器

ed
,这里有一个
ed
版本。它非常高效(
ed
是一个真正的文本编辑器)!

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

如果行号存储在变量

line
中,则:

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

只是为了取悦扎克,这是一个较少 bashism 的版本,以防你不喜欢 bash (就我个人而言,我不喜欢管道和子 shell,我更喜欢这里字符串,但是嘿,正如我所说,这只是为了取悦扎克) :

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

或(取悦索皮加尔):

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

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

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

希望这有帮助!

附注如果您觉得需要表达自己如何驾驶标准编辑器

ed
,请随时发表评论。


4
投票
cat file1 >>file2

将把 file1 的内容追加到 file2 中。

cat file1 file2

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

cat file1 file2 >file3

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

cat file1 file2 >>file3

会将文件 1 和文件 2 的串联附加到文件 3 的末尾。

编辑

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

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

或者制作 500 行文件:

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

2
投票

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

首先搭建测试环境

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

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

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

然后运行该工具即可看到惊人的结果。

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

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

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

然后运行它

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

“你的实施很糟糕!”

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

insert_at

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

并且

insert_at_replace
继续工作(当然)。
insert_at_replace
的实现也可以更改为更少的错误,但我将把它作为练习留给读者。


2
投票

如果您不介意管理新文件,我喜欢使用

head
tail
执行此操作:

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

如果您愿意,可以将其折叠成一行。然后,如果您确实需要它覆盖 file1,请执行:

mv file3 file1
(可以选择在命令之间包含
&&
)。

备注:

  • head -n 16 file1
    表示 file1 的前 16 行
  • tail -n+56 file1
    表示file1从第56行开始到结尾
  • 因此,我实际上跳过了 file1 中的第 17 行到第 55 行。
  • 当然,如果您可以将 56 更改为 17,这样就不会跳过任何行。
  • 我更喜欢混合使用简单的
    head
    tail
    命令,然后尝试神奇的
    sed
    命令。
© www.soinside.com 2019 - 2024. All rights reserved.