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