これはおそらく複雑なソリューションです。
">>" のような単純な演算子を探していますが、先頭に追加します。
私はそれが存在しないことを恐れています。私は次のようなことをしなければならないでしょう
mv myfile tmp cat myheader tmp > myfile
もっと賢いものはありますか?
これはおそらく複雑なソリューションです。
">>" のような単純な演算子を探していますが、先頭に追加します。
私はそれが存在しないことを恐れています。私は次のようなことをしなければならないでしょう
mv myfile tmp cat myheader tmp > myfile
もっと賢いものはありますか?
これはまだ一時ファイルを使用していますが、少なくとも 1 行です。
echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
クレジット: BASH: テキスト/行をファイルに追加する
echo '0a
your text here
.
w' | ed some_file
ed は標準エディターです。http://www.gnu.org/fun/jokes/ed.msg.html
以下のハックは、すぐに使える簡単な回答であり、機能し、多くの賛成票を獲得しました. その後、質問の人気が高まり、時間が経つにつれて、憤慨した人々が、それはある程度機能したが、奇妙なことが起こる可能性がある、またはまったく機能しなかったと報告し始めたため、しばらくの間、猛烈に反対票が投じられました. とても楽しい。
このソリューションは、システム上のファイル記述子の正確な実装を利用します。実装は nix 間で大幅に異なるため、成功は完全にシステムに依存し、決定的に移植性がなく、漠然と重要であっても信頼すべきではありません。
さて、それで答えは次のとおりでした。
ファイル ( )の別のファイル記述子を作成し、そのファイル ( exec 3<> yourfile
) に>&3
書き込むことで、同じファイルの読み取り/書き込みのジレンマを克服できるようです。awk を使用して 600K ファイルで動作します。ただし、「cat」を使用して同じトリックを試みると失敗します。
前置を変数として 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
John Mee: あなたのメソッドは動作することが保証されておらず、4096 バイトを超えるものを先頭に追加するとおそらく失敗します (少なくとも gnu awk ではそうなりますが、他の実装にも同様の制約があると思います)。その場合、失敗するだけでなく、独自の出力を読み取る無限ループに入り、使用可能なすべてのスペースがいっぱいになるまでファイルが大きくなります。
自分で試してみてください:
exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
(警告: しばらくしてから終了するか、ファイルシステムがいっぱいになります)
さらに、そのようにファイルを編集することは非常に危険であり、非常に悪いアドバイスです。ファイルの編集中に何かが発生した場合 (クラッシュ、ディスクがいっぱいになるなど)、ファイルが一貫性のない状態のままになることがほぼ保証されます。
一時ファイルなしでは不可能ですが、ここにワンライナーがあります
{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
ed や perl などの他のツールを使用して、一時ファイルなしで実行できます。
制御するコンピューターでこれが必要な場合は、パッケージ「moreutils」をインストールし、「sponge」を使用してください。次に、次のことができます。
cat header myfile | sponge myfile
編集するファイルが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」でのみ機能します。
シェルスクリプトで困難になることをしようとし始めたら、「適切な」スクリプト言語 (Python/Perl/Ruby/etc) でスクリプトを書き直すことを強くお勧めします。
ファイルの前に行を追加することに関しては、パイピングを介してこれを行うことはできませんcat blah.txt | grep something > blah.txt
。sponge
インストールできる小さなユーティリティ コマンドがあります (インストールするcat blah.txt | grep something | sponge blah.txt
と、ファイルの内容がバッファリングされ、ファイルに書き込まれます)。これは一時ファイルに似ていますが、明示的に行う必要はありません。しかし、それはたとえば Perl よりも「悪い」要件だと思います。
awkなどを介して行う方法があるかもしれませんが、シェルスクリプトを使用する必要がある場合は、一時ファイルが最も簡単な(/のみ?)方法だと思います..
ダニエル・ベルコフが示唆するように、ティーを使用してください。
私にとって、それはシンプルでスマートなソリューションです。
{ echo foo; cat bar; } | tee bar > /dev/null
編集:これは壊れています。catとteeを含むファイルの前に追加するときの奇妙な動作を参照してください
上書きの問題の回避策は次のtee
とおりです。
cat header main | tee main > /dev/null
sed -i -e "1s/^/new first line\n/" old_file.txt
$( command )を使用すると、コマンドの出力を変数に書き込むことができます。そのため、一時ファイルを使用せずに、3 つのコマンドを 1 行で実行しました。
originalContent=$(cat targetfile) && echo "text to prepend" > targetfile && echo "$originalContent" >> targetfile
主にファン/シェルゴルフ用ですが、
ex -c '0r myheader|x' myfile
トリックを行い、パイプラインやリダイレクトはありません。もちろん、vi/ex は実際には非対話的な使用向けではないため、vi が短時間フラッシュします。
私が使っているもの。これにより、順序、追加の文字などを好きなように指定できます。
echo -e "TEXTFIRSt\n$(< header)\n$(< my.txt)" > my.txt
PS: ファイルにバックスラッシュ付きのテキストが含まれている場合のみ機能しません。エスケープ文字として解釈されるためです。
警告:これには、OPのニーズを満たすためにもう少し作業が必要です。
@shixilunによるsedアプローチを、彼の不安にもかかわらず機能させる方法があるはずです。ファイルをsed置換文字列に読み込むときに空白をエスケープするには、bashコマンドが必要です(たとえば、改行文字を'\ n'に置き換えます。シェルコマンドは印刷できない文字vis
をcat
処理できますが、空白は処理できないため、OPは解決されません。問題:
sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt
置換スクリプトの生の改行が原因で失敗します。これは、行継続文字()を前に付け、シェルとsedを幸せに保つために、おそらく&を続ける必要があります。このSO回答のように
sed
非グローバル検索置換コマンドのサイズ制限は40Kであるため(パターンの後に/ gが続くことはありません)、匿名で警告されたawkの恐ろしいバッファオーバーランの問題を回避できる可能性があります。
これが私が発見したものです:
echo -e "header \n$(cat file)" >file
単純に ed コマンドを使用しないのはなぜですか (fluffle here で既に提案されているように)。
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 "${1}" . wq | ed -s "${2}"
}
echo 'Hello, world!' > myfile
prepend 'line to prepend' myfile
さらに別の回避策は、 Redirect output from sed 's/c/d/' myFile to myFileで Jürgen Hötzel によって提案されているように、開いているファイル ハンドルを使用することです。
echo cat > manipulate.txt
exec 3<manipulate.txt
# Prevent open file from being truncated:
rm manipulate.txt
sed 's/cat/dog/' <&3 > manipulate.txt
もちろん、これらすべてを 1 行にまとめることもできます。
固定テキストを先頭に追加するための「一時ファイルなし」のcb0のソリューションのバリアント:
echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified )
繰り返しますが、これはサブシェルの実行 ((..)) に依存しており、cat が入力と出力に同じファイルを使用することを拒否することを回避しています。
注:このソリューションが気に入りました。ただし、私の Mac では元のファイルが失われます (そうあるべきではないと思っていましたが、実際に失われます)。これは、ソリューションを次のように記述することで修正できます。猫 - file_to_be_modified | 猫 > tmp_file; mv tmp_file file_to_be_modified
sed -i -e '1rmyheader' -e '1{h;d}' -e '2{x;G}' myfile
実際、BASH でスクリプトを作成している場合は、次のように発行できます。
cat - yourfile /tmp/out && mv /tmp/out yourfile
それは実際には、あなた自身が自分の質問に投稿した複雑な例にあります。
大きなファイル (私の場合は数百キロバイト) があり、Python にアクセスできる場合、これはcat
パイプ ソリューションよりもはるかに高速です。
python -c 'f = "filename"; t = open(f).read(); open(f, "w").write("text to prepend " + t)'
変数、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
手っ取り早く、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
current=`cat my_file` && echo 'my_string' > my_file && echo $current >> my_file
ここで、「my_file」は「my_string」を先頭に追加するファイルです。
これは ed の最もクリーンなバリエーションだと思います:
cat myheader | { echo '0a'; cat ; echo -e ".\nw";} | ed myfile
関数として:
function prepend() { { echo '0a'; cat ; echo -e ".\nw";} | ed $1; }
cat myheader | prepend myfile
@fluffle のedアプローチが一番好きです。結局のところ、ツールのコマンド ライン スイッチとスクリプト エディター コマンドは本質的に同じものです。スクリプト化されたエディター ソリューションの「クリーンさ」が劣っているとは見なされません。
これは、メッセージをコミットするため.git/hooks/prepare-commit-msg
にレポ内ファイルを先頭に追加するために追加されたワンライナーです。.gitmessage
echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s "$1"
例.gitmessage
:
# Commit message formatting samples:
# runlevels: boot +consolekit -zfs-fuse
#
元のテンプレートのファイルの上に書き込み可能な空の行が残るため、1r
代わりに を実行しています。0r
thenの上に空行を置かないでください.gitmessage
。空行が 2 行になってしまいます。-s
ed の診断情報の出力を抑制します。
これに関連して、私は vim-buffs のために以下を持っていることも良いことを発見しました:
[core]
editor = vim -c ':normal gg'
Bah! No one cared to mention about 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 bug-coreutils@gnu.org
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/>