到目前为止,我已经能够找出如何在文件开头添加一行,但这并不是我想要的。我将用一个例子来展示它:
文件内容
some text at the beginning
结果
<added text> some text at the beginning
它很相似,但我不想用它创建任何新行......
如果可能的话,我想用 sed
来做这件事。
sed
。
sed
可以对地址进行操作:
$ sed -i '1s/^/<added text> /' file
您在此处的每个答案中看到的这个神奇的 1s
是什么? Line addressing!。
想要在前 10 行添加 <added text>
?
$ sed -i '1,10s/^/<added text> /' file
或者您可以使用 Command Grouping
:
$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
如果要在文件开头添加一行,则需要在上述最佳解决方案中的字符串末尾添加 \n
。
最好的解决方案是添加字符串,但是使用字符串,它不会在文件末尾添加一行。
sed -i '1s/^/your text\n/' file
sed
版本下,您必须提供带有 -i
选项的备份文件名。一个人可以只传递一个空字符串而没有像 sed -i '' '1s/^/new test\n/' filename
这样的备份
如果文件只有一行,您可以使用:
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
进行就地编辑。
使用子外壳:
echo "$(echo -n 'hello'; cat filename)" > filename
不幸的是,命令替换将删除文件末尾的换行符。为了保留它们,可以使用:
echo -n "hello" | cat - filename > /tmp/filename.tmp
mv /tmp/filename.tmp filename
既不需要分组也不需要命令替换。
sed
的所有其他解决方案的优越和简单的解决方案,它不适用于空文件。
只插入一个换行符:
sed '1i\\'
您可以使用 cat -
printf '%s' "some text at the beginning" | cat - filename
echo
添加换行符?
> file
附加到命令来将其定向到文件中,它只是用 "some text at the beginning"
向我的终端发送垃圾邮件
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
在文件顶部添加一行:
sed -i '1iText to add\'
我的两分钱:
sed -i '1i /path/of/file.sh' filename
即使是包含正斜杠 "/"
的字符串,这也将起作用
回车您好:
sed -i '1s/^/your text\n/' file
请注意,在 OS X 上,sed -i <pattern> file
失败。但是,如果您提供备份扩展 sed -i old <pattern> file
,则在创建 file.old
的同时修改 file
。然后,您可以删除脚本中的 file.old
。
有一个非常简单的方法:
echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
问题:用父目录的基本名称在文件顶部标记文件。
即,对于
/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),并将该文件和文件放到 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 ...
类型的解决方案)。
附录:回复:我的最后一条评论,此脚本将允许您递归路径中带有空格的目录:
#!/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
只是为了好玩,这里有一个使用 ed
的解决方案,它不存在无法处理空文件的问题。您可以将其放入 shell 脚本中,就像此问题的任何其他答案一样。
ed Test <<EOF
a
.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF
上面的脚本将要插入的文本添加到第一行,然后连接第一行和第二行。为避免 ed 因无效连接出错而退出,它首先在文件末尾创建一个空行,如果它仍然存在,稍后将其删除。
限制:如果 <added text>
正好等于单个句点,则此脚本不起作用。
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt
第一个 tac
向后管道传输文件(最后一行在前),因此“要插入的文本”最后出现。第二个 tac
再次包装它,因此插入的行位于开头,原始文件按其原始顺序排列。
另一个带有别名的解决方案。添加到您的 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 附加到文件中。示例: # 使其可执行(使用 u+x 只允许当前用户) chmod +x cropImage.ts # 附加 shebang echo '#''!'/usr/bin/env ts-node |猫-cropImage.ts | tee cropImage.ts &> /dev/null # 执行 ./cropImage.ts myImage.png
TL;博士-
考虑使用 ex
。由于您想要给定行的前面,因此语法与 sed
的语法基本相同,但“就地编辑”选项是内置的。
我无法想象你有 sed
但没有 ex
/vi
的环境,除非它是一个带有一些特殊“sed.exe”的 MS Windows 机器,也许。
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
。
source=myFile.txt
topString="****** This goes on TOP ******"
man true > "$source"
ex -s ${source} <<-EOF
0r!echo "$topString"
wq
EOF
0r
是您可能在 vi
模式下使用过的 :0read!
或 :0r!
的简写(字面意思相同),但 :
在这里是可选的。
写入特殊行 #0 会自动将所有内容“向下”推送,然后您只需 :wq
即可保存您的更改。
$ head -n 5 "$source"
****** This goes on TOP ******
TRUE(1) User Commands TRUE(1)
NAME
true - do nothing, successfully
此外,一些较旧的 sed
实现似乎没有 ex
默认应具有的扩展(如 \U&
)。
不定期副业成功案例分享