如何在文件的开头插入文本?

到目前为止,我已经能够找出如何在文件的开头添加一行,但这并不完全是我想要的。我将用一个例子来说明:

文件内容

some text at the beginning

结果

<added text> some text at the beginning

它很相似,但是我不想用它创建任何新的行…

如果可能的话,我想用sed这样做。

395252 次浏览

如果文件只有一行,你可以使用:

sed 's/^/insert this /' oldfile > newfile

如果它不止一行。之一:

sed '1s/^/insert this /' oldfile > newfile
sed '1,1s/^/insert this /' oldfile > newfile

我已经包括了后者,以便您知道如何进行行范围。这两种方法都用要插入的文本“替换”受影响行的开始行标记。你还可以(假设你的sed足够现代)使用:

sed -i 'whatever command you choose' filename

进行就地编辑。

sed可以作用于地址:

$ sed -i '1s/^/<added text> /' file

你在每个答案上看到的神奇1s是什么?行解决!

想在前10行添加<added text>吗?

$ sed -i '1,10s/^/<added text> /' file

或者你可以使用Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}

嗨,用马车回:

sed -i '1s/^/your text\n/' file

如果你想在文件的开头添加一行,在上面的最佳解决方案中,你需要在字符串的末尾添加\n

最好的解决方案是添加字符串,但是使用字符串,它不会在文件的末尾添加一行。

sed -i '1s/^/your text\n/' file

你可以使用cat -

printf '%s' "some text at the beginning" | cat - filename
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt

第一个tac反向传输文件(最后一行在前),因此“要插入的文本”出现在最后。第2 tac再次将其换行,因此插入的行位于开头,原始文件处于原始顺序。

注意,在OS X上,sed -i <pattern> file失败。然而,如果你提供了一个备份扩展,sed -i old <pattern> file,那么在创建file.old时,file会被修改。然后你可以在你的脚本中删除file.old

插入换行符:

sed '1i\\'

在文件顶部添加一行:

sed -i '1iText to add\'

问题:标记一个文件,在文件的顶部,带有父目录的基本名称。

例如,对

/mnt/Vancouver/Programming/file1

Programming标记file1的顶部。

解决方案1——非空文件:

bn=${PWD##*/}    ## bn: basename


sed -i '1s/^/'"$bn"'\n/' <file>

1s将文本放在文件的第1行。

解决方案2——空文件或非空文件:

上面的sed命令在空文件上失败。下面是一个基于https://superuser.com/questions/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash/246841#246841的解决方案

printf "${PWD##*/}\n" | cat - <file> > temp && mv -f temp <file>

注意cat命令中的-是必需的(读取标准输入:有关更多信息,请参阅man cat)。在这里,我相信,它需要接受printf语句的输出(到STDIN),并将其和文件cat到temp…另见http://www.linfo.org/cat.html底部的解释。

我还在mv命令中添加了-f,以避免在覆盖文件时被要求确认。

递归遍历一个目录:

for file in *; do printf "${PWD##*/}\n" | cat - $file > temp && mv -f temp $file; done

还要注意,这将用空格分隔路径;有解决方案,在其他地方(例如文件通配符,或find . -type f ...类型的解决方案)。

附录: Re:我的最后一个注释,这个脚本将允许你递归路径中有空格的目录:

#!/bin/bash


## https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi


## To allow spaces in filenames,
##   at the top of the script include: IFS=$'\n'; set -f
##   at the end of the script include: unset IFS; set +f


IFS=$'\n'; set -f


# ----------------------------------------------------------------------------
# SET PATHS:


IN="/mnt/Vancouver/Programming/data/claws-test/corpus test/"


# https://superuser.com/questions/716001/how-can-i-get-files-with-numeric-names-using-ls-command


# FILES=$(find $IN -type f -regex ".*/[0-9]*")        ## recursive; numeric filenames only
FILES=$(find $IN -type f -regex ".*/[0-9 ]*")         ## recursive; numeric filenames only (may include spaces)


# echo '$FILES:'                                      ## single-quoted, (literally) prints: $FILES:
# echo "$FILES"                                       ## double-quoted, prints path/, filename (one per line)


# ----------------------------------------------------------------------------
# MAIN LOOP:


for f in $FILES
do


# Tag top of file with basename of current dir:
printf "[top] Tag: ${PWD##*/}\n\n" | cat - $f > temp && mv -f temp $f


# Tag bottom of file with basename of current dir:
printf "\n[bottom] Tag: ${PWD##*/}\n" >> $f
done


unset IFS; set +f

有一个非常简单的方法:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt

只是为了好玩,这里有一个使用ed的解决方案,它没有不能在空文件上工作的问题。您可以把它放到一个shell脚本中,就像这个问题的任何其他答案一样。

ed Test <<EOF
a


.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF

上面的脚本将要插入的文本添加到第一行,然后连接第一行和第二行。为了避免ed在无效连接错误时退出,它首先在文件末尾创建一个空行,如果它仍然存在,则稍后删除它。

限制:如果<added text>恰好等于一个句点,此脚本将不起作用。

我的观点是:

sed  -i '1i /path/of/file.sh' filename

即使字符串包含正斜杠"/",这也可以工作

使用shell:

echo "$(echo -n 'hello'; cat filename)" > filename

不幸的是,命令替换将删除文件末尾的换行符。为了保持它们,人们可以使用:

echo -n "hello" | cat - filename > /tmp/filename.tmp
mv /tmp/filename.tmp filename

既不需要分组,也不需要命令替换。

别名是另一种解决方案。添加到你的init rc/ env文件:

addtail () { find . -type f ! -path "./.git/*" -exec sh -c "echo $@ >> {}" \; }
addhead () { find . -type f ! -path "./.git/*" -exec sh -c  "sed -i '1s/^/$@\n/' {}" \; }

用法:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"

使用echo方法,如果你像我一样在macOS/BSD上,就丢掉其他人建议的-n开关。我喜欢为文本定义一个变量。

所以它是这样的:

Header="my complex header that may have difficult chars \"like these quotes\" and line breaks \n\n "


{ echo "$Header"; cat "old.txt"; } > "new.txt"
mv new.txt old.txt

我找到的最简单的解决方法是:

echo -n "<text to add>" | cat - myFile.txt | tee myFile.txt

注:

  • 如果你不想改变文件内容,移除| tee myFile.txt
  • 如果你想追加一个完整的行,移除-n参数。
  • 如果不想看到输出(生成的文件),则在末尾添加&> /dev/null
  • 可以用来在文件中追加一个shebang。例子:
    # make it executable (use u+x to allow only current user)
    chmod +x cropImage.ts
    # append the shebang
    echo '#''!'/usr/bin/env ts-node | cat - cropImage.ts | tee cropImage.ts &> /dev/null
    # execute it
    ./cropImage.ts myImage.png
    

博士TL; -

考虑使用ex。因为你想要在给定行的前面,那么语法基本上与你可能在sed中找到的语法相同,但是选项“in place editing"是内置的。

我无法想象有sed但没有ex/vi的环境,除非它是一个MS Windows盒子,可能有一些特殊的“sed.exe”。

sed,grep在某种程度上是从ex / vi演变而来的,因此更好的说法是sed语法与ex相同。

您可以将行号更改为#1以外的内容,或者搜索一行并更改该行。

source=myFile.txt
Front="This goes IN FRONT "
man true > $source
ex -s ${source} <<EOF
1s/^/$Front/
wq
EOF
$ head -n 3 $source
This goes IN FRONT TRUE(1)                                                    User Commands                                                    TRUE(1)


NAME

长版本,我推荐ex(或ed,如果你是一个很酷的孩子)。

我喜欢ex,因为它是可移植的,非常强大,允许我在不需要GNU(甚至BSD)扩展的情况下进行就地编写和/或备份。

此外,如果你知道ex方法,那么你就知道如何在vi中做——如果你擅长的话,可能还会在vim中做。 注意,当我们使用"i"nsert并使用echo:

时,EOF没有被引用
str="+++ TOP +++" && ex -s <<EOF
r!man true
1i
`echo "$str"`
.
"0r!echo "${str}"
wq! true.txt
EOF


0r!echo "${str}"也可以作为:0read!:0r!的简写,你可能在vi模式中使用过(它是字面上的相同的东西),但:在这里是可选的,一些实现不支持" "ead地址为0。 直接读取到特殊行#0(或从第1行开始)会自动将所有内容“下推”,然后你只需:wq保存你的更改
$ head -n 3 true.txt | nl -ba
1  +++ TOP +++
2  TRUE(1)                          User Commands                         TRUE(1)
3

此外,大多数经典的sed实现都没有默认情况下ex应该具有的扩展(如\U&)。