在问题中如何将多行追加到文件中OP 正在寻找一种将多行附加到 shell 内的文件的方法。解决方案:
cat <<EOT >> test.txt
line 1
line 2
EOT
我想在前面添加行,我的尝试如下所示:
echo 3 >test.text
cat test.text <<EOT >> test.text
1
2
EOT
但这会导致错误:
cat: test.text: input file is output file
编辑:为了澄清起见,我正在遵循一份很长的服务器设置指南,其中包含手动编辑配置文件的说明。编辑有时涉及将文本块添加到文件中。在自动化某些步骤时,我想通过按原样复制指南中的文本并将其放入 bash 单行代码中来保留命令的冗长性。因此,EOT
首选使用多行文本输入。
编辑:使用 sed 的其他答案要求将反斜杠附加到每行的末尾,但我想输入多行而不进行修改。
有没有办法以与上面类似的方式在文件前面添加多行(理想情况下没有临时文件和安装moreutils
)?
答案1
最安全的方法是将原始文件复制到临时位置,并将新内容与该文件连接到旧名称中:
tmpfile=$(mktemp)
cp myfile "$tmpfile" &&
cat - "$tmpfile" <<NEW_CONTENTS >myfile
this is
new contents
at top of file
NEW_CONTENTS
rm "$tmpfile"
请注意,cat
命令本身是几乎和你的一样
cat myfile <<EOT >>myfile
1
2
3
EOT
但是,cat
必须告诉它还读取其标准输入,当其文件名操作数之一是 时,它会执行此操作-
。我们也无法从原始文件重定向,然后将结果附加到同一个文件,因为这会创建一个循环,使文件不断增长,直到填满分区上的所有空间。这就是为什么我首先将文件复制到临时文件,然后使用它为旧名称创建新内容。
我们也可以这样做
tmpfile=$(mktemp)
cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
this is
new contents
at top of file
NEW_CONTENTS
mv "$tmpfile" myfile
即,将结果写入临时文件,然后移动它以替换原始文件。但是,此操作顺序不能保证保留 的所有权和权限myfile
。
一个小型 shell 函数,它接受标准输入并将其放置在给定文件名的顶部:
paste_header () {
local tmpfile=$(mktemp)
trap "rm -f '$tmpfile'" EXIT
cat - "$1" >"$tmpfile" &&
cat "$tmpfile" >"$1"
}
例如,这种编写方式允许用户以交互方式粘贴剪贴板中的内容,但如果输入被 中断,则不会修改原始文件Ctrl+C。交互式输入需要通过按Ctrl+D(发送EOT
,即文本结束)来终止。
该函数将用作
paste_header filename
以交互方式粘贴要添加到的数据filename
(以 结束输入Ctrl+D)。
或者
paste_header filename <otherfile
从另一个文件插入数据。
答案2
如果您需要读取命令的输出,您可以使用ed
链接问题中的方法,并进行以下变体:
ed -s test.txt <<< $'0r !echo stuff\nw\nq'
这r
会将命令的输出echo stuff
写入test.txt
零行之后。
要通过here-doc在第一行之前插入多行文本,您需要运行
ed -s test.txt <<EOT
1i
add some line
and some more
to the beginning
.
w
q
EOT
该点表示输入模式的结束,这意味着最后一个解决方案假设您的文本不包含由单个点组成的行。
答案3
你可以使用普通的 ol'前文本编辑器它应该在几乎所有 POSIX 兼容系统中可用。
要插入第一行,只需执行以下操作
ex -sc '1i|new first line' -cx test.txt
对于要添加多行的情况,只需在循环中添加行,最后添加最上面的元素(就像堆栈一样)
for number in 5 4 3 2 1; do
ex -sc '1i|'"$number"'' -cx newfile
done
of 如果想避免对文件进行多次写操作,则将多行内容构造一个变量,直接插入
multiple_lines=$'line1\nline2\nline3\nline4\nline5\n'
ex -sc '1i|'"$multiple_lines"'' -cx newfile
答案4
使用 sed:
$ sed -e 'i1' -e 'i2' test.text
1
2
3