shell一个衬班要添加到文件
这可能是一个复杂的解决方案。
我正在寻找一个像">>"这样的简单操作员,而是为了预先补习。
我担心它不存在。
我必须做一些这样的事情
mv myfile tmp cat myheader tmp > myfile
更聪明的是什么?
解决方案
这仍然使用临时文件,但至少它是一行:
echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
Credit:Bash:将文本/行添加到文件中
没有临时文件,但在这里不可能是一个oneliner
{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
我们可以使用其他工具,例如ed或者perl,而不是临时文件。
如果我们在Bash中脚本,实际上,我们可以签发:
cat - yourfile /tmp/out && mv /tmp/out yourfile
这实际上是我们自己在我们自己的问题中发布的复杂示例。
值得注意的是,它通常是使用MKTEMP等实用程序安全地生成临时文件的好主意,至少如果脚本将被用root权限执行。
例如,我们可以执行以下操作(再次在Bash中):
(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )
当我们开始尝试在Shell脚本中进行困难的事情时,我将强烈建议在"正确"脚本语言(Python / Perl / Ruby / etc)中重写脚本
至于将一行提前输入文件,通过管道无法执行此操作,就像我们这样做的任何像'CAT BLAH.TXT时grep something> blah.txt',它无意中为文件空白。
有一个名为'海绵'的小实用程序命令,我们可以安装(我们做'cat blah.txt | grep something | sponge blah.txt',它缓冲了文件的内容,然后将其写入文件)。
它类似于临时文件,但我们不必明确执行此操作。
但我会说这是一个"更糟糕的"的要求,而不是说Perl。
可能有一种方法可以通过awk或者类似,但如果你必须使用shell脚本,我认为一个临时文件是迄今为止最简单的(/只?
)方式。
下面的黑客是一个快速的袖口答案,工作和接受了许多升值。
然后,由于问题变得更加流行,更多的时间通过,愤怒的人开始报告它的工作,但奇怪的事情可能发生,或者它只是没有工作,所以这是一段时间疯狂地下降。
好好玩。
该解决方案利用系统上的文件描述符的精确实现,因为在NIXE之间的实施中的实现显着变化,这取得了成功,完全是系统依赖性,绝对不便携的,并且不应该依靠模糊不可依赖的。
现在,答案的所有方式都是:
创建文件的另一个文件描述符('exec 3 <> yourfile'),从那时写入('>&3')似乎克服了同一文件困境的读/写。
用扶手上的600k文件为我工作。
然而,使用"猫"失败尝试同样的伎俩。
将Prependage作为变量传递给AWK('-V text ="$ text"')克服了文字引号问题,这可以使用'sed'执行此技巧。
#!/bin/bash text="Hello world What's up?" exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
假设要编辑的文件是my.txt
$cat my.txt this is the regular file
我们要预付的文件是标题
$ cat header this is the header
请务必在头文件中有一个最终的空白行。
现在你可以用它预付它
$cat header <(cat my.txt) > my.txt
你最终结束了
$ cat my.txt this is the header this is the regular file
据我所知,这只能在'bash'工作。
CB0的一个变体为"NO TEMP文件"的解决方案中的解决方案,以预先修复修复文本:
echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified )
这再次依赖于子shell执行(..),以避免拒绝具有相同的输入和输出的文件。
注意:喜欢此解决方案。
但是,在我的Mac中,原始文件丢失(认为它不应该但它不应该)。
这可以通过将解决方案写作:
echo"prepend文本"| cat file_to_be_modified |猫> tmp_file; mv tmp_file file_to_be_modified.
呸!没有人关心tac。
endor@grid ~ $ tac --help Usage: tac [OPTION]... [FILE]... Write each FILE to standard output, last line first. With no FILE, or when FILE is -, read standard input. Mandatory arguments to long options are mandatory for short options too. -b, --before attach the separator before instead of after -r, --regex interpret the separator as a regular expression -s, --separator=STRING use STRING as the separator instead of newline --help display this help and exit --version output version information and exit Report tac bugs to [email protected] GNU coreutils home page: <http://www.gnu.org/software/coreutils/> General help using GNU software: <http://www.gnu.org/gethelp/> Report tac translation bugs to <http://translationproject.org/team/>
current=`cat my_file` && echo 'my_string' > my_file && echo $current >> my_file
其中"my_file"是将"my_string"添加到的文件。
John Mee:方法无法保证工作,如果我们预先添加了超过4096个字节的东西(至少是GNU AWK发生的事情,但我认为其他实现将具有类似的约束)。
在这种情况下,它不仅会失败,而且它将进入一个无休止的循环,在那里它将读取自己的输出,从而使文件增长,直到填充所有可用空间。
为自己试试:
exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
(警告:在一段时间后杀死它,或者它将填充文件系统)
此外,编辑文件是非常危险的,这是非常糟糕的建议,好像在编辑文件时发生某些东西(崩溃,磁盘满),我们几乎保证以不一致的状态留下文件。
echo '0a your text here . w' | ed some_file
ed是标准编辑器! http://www.gnu.org/fun/jokes/ed.msg.html.
sed -i -e "1s/^/new first line\n/" old_file.txt
编辑:这是破碎的。
准备好猫和多特群的文件时,请参阅奇怪行为
覆盖问题的解决方法使用"TEE":
cat header main | tee main > /dev/null
警告:这需要更多的工作来满足OP的需求。
尽管他的疑虑,应该有一种方法可以通过@shixilun制作SED方法。
必须有一个bash命令在将文件读入sed替换字符串时逃脱空格(例如,用'\ n'替换换行符。
shell命令'vis'和'cat'可以处理非打印字符,但不是空格,所以它不会解决OP的问题:
sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt
由于替代脚本中的原始换行符而失败,需要使用线路延续字符(),也许是一个&,以保持shell和sed快乐,如此答案
"SED"的尺寸限制为40K用于非全局搜索 - 替换命令(模式后没有尾随/ g)所以可能避免匿名警告的AWK的可怕缓冲区溢出问题。
为什么不仅仅是使用ED命令(如图所示的垃圾)?
ED将整个文件读入内存并自动执行就地文件编辑!
所以,如果你的文件不是那么大......
# cf. "Editing files with the ed text editor from scripts.", # http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed prepend() { printf '%s\n' H 1i "" . wq | ed -s "" } echo 'Hello, world!' > myfile prepend 'line to prepend' myfile
另一个解决方法将使用J眉RGENHH?
Tzel从Sed'S / C / D / D /'MyFile重定向输出到MyFile中的打开文件处理
echo cat > manipulate.txt exec 3<manipulate.txt # Prevent open file from being truncated: rm manipulate.txt sed 's/cat/dog/' <&3 > manipulate.txt
当然,这一切都可以放在一行上。
我使用的那个。
这一个允许我们以我们喜欢的方式指定订单,额外的字符等:
echo -e "TEXTFIRSt\n$(< header)\n$(< my.txt)" > my.txt
P.S:如果文件包含Backslash的文本,则才能运行,导致它被解释为转义字符
我喜欢@ fluffle的ed方法是最好的。
毕竟,任何工具的命令行交换机与脚本编辑器命令在此处基本上是相同的;没有看到脚本的编辑器解决方案"清洁"是任何较小的或者何时。
这是我的一班林添加到'.git / hooks / prepare-commm-msg'以预先提交in-repo'.gitmessage'文件来提交消息:
echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s ""
示例'.gitmessage':
# Commit message formatting samples: # runlevels: boot +consolekit -zfs-fuse #
我正在做'1R'而不是'0R',因为这将从原始模板上留下文件顶部的空现代写入线。
不要在'.gitmessage'之上放置一个空线,你将最终有两个空线。
'-s'抑制ed的诊断信息输出。
与越来越通过这个,我发现对于Vim-Buff,它也很好:
[core] editor = vim -c ':normal gg'
变量,ftw?
NEWFILE=$(echo deb http://mirror.csesoc.unsw.edu.au/ubuntu/ $(lsb_release -cs) main universe restricted multiverse && cat /etc/apt/sources.list) echo "$NEWFILE" | sudo tee /etc/apt/sources.list
这是我发现的:
echo -e "header \n$(cat file)" >file
像Daniel Velkov建议,使用T恤。
对我来说,这是简单的智能解决方案:
{ echo foo; cat bar; } | tee bar > /dev/null
sed -i -e '1rmyheader' -e '1{h;d}' -e '2{x;G}' myfile
我认为这是ED的最新变化:
cat myheader | { echo '0a'; cat ; echo -e ".\nw";} | ed myfile
作为一个功能:
function prepend() { { echo '0a'; cat ; echo -e ".\nw";} | ed ; } cat myheader | prepend myfile
如果我们在控制的计算机上需要它,请安装"moututils"包并使用"海绵"。
然后你可以做:
cat header myfile | sponge myfile
主要是为了有趣/贝壳高尔夫,但是
ex -c '0r myheader|x' myfile
将做诀窍,没有管道或者重定向。
当然,VI / EX并不是真正的非交互式使用,因此VI将简要闪烁。
使用$(命令),我们可以将命令的输出写入变量。
所以我在一行中的三个命令中完成了它,没有临时文件。
originalContent=$(cat targetfile) && echo "text to prepend" > targetfile && echo "$originalContent" >> targetfile
imho没有shell解决方案(并且永远不会是一个),这将一致地和可靠地工作,无论两个文件'myheader'和'myfile'的大小。
原因是,如果我们想在不重新定位到临时文件的情况下(而不让Shell默默地默认到临时文件的情况下,例如,通过像'EXEC 3 <> MYFILE',管道为'TEE'等)。
我们正在寻找的"真实"解决方案需要小提琴与文件系统,因此它在用户空间中没有可用,并且将依赖于平台:我们要求在使用"myfile"的当前值时修改文件系统指针"MyHeader"的文件系统指针并替换为"MyHeader"的"eof"的文件系统,其中包含"MyFile"指向当前文件系统地址的链接。
这并不是微不足道的,显然不能由非超级用户完成,并且可能不是超级用户......与in inode等。
但是,我们可以使用循环设备或者多或者少地伪造这一点。
看上来这么好。
如果我们有一个大文件(在我的情况下几百千字节)并访问Python,那么这比"猫"的管道解决方案更快:
'python -c'f ="filename"; t =打开(f).read();打开(f,"w")。
写("要预付"文本"+ T)''
使用Bash Heredoc,我们可以避免需要TMP文件:
cat <<-EOF > myfile $(echo this is prepended) $(cat myfile) EOF
这是因为在评估Bash脚本时评估了$(CAT MyFile),在执行重定向时进行评估。
快速且脏,缓冲与python内存中的所有内容:
$ echo two > file $ echo one | python -c "import sys; f=open(sys.argv[1]).read(); open(sys.argv[1],'w').write(sys.stdin.read()+f)" file $ cat file one two $ # or creating a shortcut... $ alias prepend='python -c "import sys; f=open(sys.argv[1]).read(); open(sys.argv[1],\"w\").write(sys.stdin.read()+f)"' $ echo zero | prepend file $ cat file zero one two
具有"Printf"的解决方案:
new_line='the line you want to add' target_file='/file you/want to/write to' printf "%s\n$(cat ${target_file})" "${new_line}" > "${target_file}"
你也可以做:
printf "${new_line}\n$(cat ${target_file})" > "${target_file}"
但在这种情况下,我们必须确保在任何地方不得不在那里,包括目标文件的内容,因为可以解释并搞定结果。
我们可以使用Perl命令行:
perl -i -0777 -pe 's/^/my_header/' tmp
其中-i将创建文件的内联替换文件
-0777将啜饮整个文件并使^仅匹配开头。
-pe将打印所有的行
或者如果my_header是文件:
perl -i -0777 -pe 's/^/`cat my_header`/e' tmp
/ E将允许替换中的代码评估。