Unix命令将文本添加到文件中

Unix command to prepend text to a file

是否有Unix命令将一些字符串数据添加到文本文件中?

就像是:

1
prepend"to be prepended" text.txt


1
2
3
printf '%s
%s
'"to be prepended""$(cat text.txt)">text.txt


1
sed -i.old '1s;^;to be prepended;' inFile
  • -i将更改写入到位,并在给出任何扩展名时进行备份。 (在这种情况下,.old)
  • 1s;^;to be prepended;使用;作为命令分隔符,用给定的替换字符串替换第一行的开头。


流程替代

我很惊讶没有人提到这一点。

1
cat <(echo"before") text.txt > newfile.txt

这可以说比接受的答案更自然(打印一些东西并将其输入到替换命令中,这是字典上反直觉的)。

...并且劫持了上面所说的ryan,用sponge你不需要临时文件:

1
2
sudo apt-get install moreutils
<<(echo"to be prepended") < text.txt | sponge text.txt

编辑:看起来这在Bourne Shell /bin/sh中不起作用

这里是String

使用here-string - <<<(再次,你需要bash),你可以这样做:

1
<<<"to be prepended" < text.txt | sponge text.txt


这是一种可能性:

1
(echo"to be prepended"; cat text.txt) > newfile.txt

你可能不会轻易绕过中间文件。

替代方案(shell逃逸可能很麻烦):

1
sed -i '0,/^/s//to be prepended/' text.txt


这将有助于形成输出。 - 表示标准输入,通过回声管道提供。

1
2
echo -e"to be prepended
 another line" | cat - text.txt

要重写文件,需要临时文件,因为无法管道输入到输入文件中。

1
2
echo"to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt


更喜欢亚当的回答

我们可以更容易地使用海绵。现在我们不需要创建临时文件并将其重命名

1
2
echo -e"to be prepended
 another line" | cat - text.txt | sponge text.txt


在某些情况下,前置文本只能从stdin获得。
那么这种组合应该有效。

1
echo"to be prepended" | cat - text.txt | tee text.txt

如果要省略tee输出,则追加> /dev/null


可能没有任何内置功能,但您可以轻松编写自己的内容,如下所示:

1
2
3
4
#!/bin/bash
echo -n"$1"> /tmp/tmpfile.$$
cat"$2">> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$"$2"

这样的东西至少......


解:

1
2
printf '%s
%s' 'text to prepend'"$(cat file.txt)"> file.txt

请注意,这对所有类型的输入都是安全的,因为没有扩展。例如,如果您想要预先添加!@#$%^&*()ugly text
\t
,它将起作用:

1
2
3
4
printf '%s
%s' '!@#$%^&*()ugly text
\t
'"$(cat file.txt)"> file.txt

剩下要考虑的最后一部分是在命令替换"$(cat file.txt)"期间在文件末尾删除空格。所有解决方法都相对复杂。如果要在file.txt结尾处保留换行符,请参阅:https://stackoverflow.com/a/22607352/1091436


如果替换输入文件是可以接受的:

注意:这样做可能会产生意外的副作用,特别是用常规文件替换符号链接,可能以文件的不同权限结束,以及更改文件的创建(出生)日期。

sed -i,如约翰·韦斯利亲王的回答,试图至少恢复原始权限,但其他限制适用。

1
2
3
 { printf 'line 1
line 2
'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt

注意:使用组命令{ ...; ... }比使用子shell((...; ...))更有效。

如果输入文件应该就地编辑(保留其inode及其所有属性):

使用古老的ed POSIX实用程序:

注意:ed总是首先将输入文件作为整体读入内存。

1
2
3
4
5
6
7
ed -s text.txt <<'EOF'
1i
line 1
line 2
.
w
EOF
  • -s抑制了ed的状态消息。
  • 注意命令如何作为多行here-文档(<<'EOF' ... EOF)提供给ed,即通过stdin。
  • 1i使1(第1行)成为当前行并开始插入模式(i)。
  • 以下行是在当前行之前插入的文本,在其自己的行上以.结尾。
  • w将结果写回输入文件(用于测试,将w替换为,p仅打印结果,而不修改输入文件)。

在Bash(在Ubuntu中)测试过,如果从测试文件开始经过;

echo"Original Line"> test_file.txt

你可以执行;

echo"$(echo"New Line"; cat test_file.txt)"> test_file.txt

或者,如果bash的版本对于$()来说太旧了,你可以使用反引号;

echo"`echo"New Line"; cat test_file.txt`"> test_file.txt

并收到"test_file.txt"的以下内容;

1
2
New Line
Original Line

没有中间文件,只是bash / echo。


使用sed的另一种方法:

1
2
sed -i.old '1 {i to be prepended
}' inFile

如果要预先添加的行是多行:

1
2
3
4
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile


另一个相当直接的解决方案是:

1
2
    $ echo -e"string
" $(cat file)


如果你喜欢vi / vim,这可能更符合你的风格。

1
2
3
4
5
printf '0i
%s
.
wq
' prepend-text | ed file

我真的不喜欢这里的任何答案,所以我建立了自己的命令:pre

安装go:

go get -u github.com/Flaque/pre

将stdin中的一些文本预先添加到文件中:

echo"some at the start" | pre myFile.txt | sponge myFile.txt

该命令不会写入,它只是输出到stdout,所以你需要来自moreutilssponge来保存文件。


我建议定义一个函数,然后在需要的地方导入和使用它。

1
2
3
4
5
6
7
8
9
10
11
12
prepend_to_file() {
    file=$1
    text=$2

    if ! [[ -f $file ]] then
        touch $file
    fi

    echo"$text" | cat - $file > $file.new

    mv -f $file.new $file
}

然后像这样使用它:

1
2
prepend_to_file test.txt"This is first"
prepend_to_file test.txt"This is second"

您的文件内容将是:

1
2
This is second
This is first

我即将使用这种方法来实现更改日志更新程序。


1
2
3
4
5
6
7
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing"jim" to the file
sed -i"1s/^/jim
/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo