文字列データをテキストファイルの前に追加するUnixコマンドはありますか?
何かのようなもの:
prepend "to be prepended" text.txt
文字列データをテキストファイルの前に追加するUnixコマンドはありますか?
何かのようなもの:
prepend "to be prepended" text.txt
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
sed -i.old '1s;^;to be prepended;' inFile
-i
変更をその場で書き込み、拡張子が指定されている場合はバックアップを取ります。(この場合、.old
)1s;^;to be prepended;
;
コマンド区切り文字として使用して、最初の行の先頭を指定された置換文字列に置き換えます。誰もこれについて言及していないことに驚いています。
cat <(echo "before") text.txt > newfile.txt
これは、受け入れられた答えよりも間違いなく自然です(何かを印刷して置換コマンドにパイプすることは、辞書式順序で直感に反します)。
...そしてライアンが上で言ったことをハイジャックしsponge
ます。一時ファイルは必要ありません。
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
編集:これはBourneShellでは機能しないようです/bin/sh
here-string-を使用すると<<<
、次のことができます。
<<< "to be prepended" < text.txt | sponge text.txt
これは1つの可能性です:
(echo "to be prepended"; cat text.txt) > newfile.txt
おそらく、中間ファイルを簡単に回避することはできません。
代替案(シェルのエスケープで面倒な場合があります):
sed -i '0,/^/s//to be prepended/' text.txt
これは、出力を形成するために機能します。-は、エコーからパイプを介して提供される標準入力を意味します。
echo -e "to be prepended \n another line" | cat - text.txt
ファイルを書き換えるには、入力ファイルにパイプバックできないため、一時ファイルが必要です。
echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
ノート:
これを行うと、予期しない副作用が発生する可能性があります。特に、シンボリックリンクが通常のファイルに置き換えられ、ファイルに対するアクセス許可が異なり、ファイルの作成(誕生日)日が変更される可能性があります。
sed -i
、ジョンウェスレー王子の回答のように、少なくとも元の権限を復元しようとしますが、他の制限も適用されます。
一時ファイルを使用する簡単な代替方法を次に示します( shimeのソリューションのように入力ファイル全体をメモリに読み込むことを回避します)。
{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
0xC0000022Lのソリューションのように、グループコマンド( )を使用する方が、サブシェル(){ ...; ...; }
を使用するよりもわずかに効率的です。(...; ...)
利点は次のとおりです。
新しいテキストを最初の行に直接追加するか、新しい行として挿入するか(引数に追加\n
するだけ)を簡単に制御できます。printf
ソリューションとは異なり、sed
入力ファイルが空(0
バイト)の場合に機能します。
既存のコンテンツの前に1行以上を追加することが目的の場合sed
(入力ファイルが空でない場合) 、ソリューションを簡略化できます。
sed
のi
関数は行全体を挿入します。
GNU の場合sed
:
# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile
macOS / BSDでも動作するポータブルバリアントsed
:
# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile
の後のリテラル改行\
が必要であることに注意してください。
由緒あるed
POSIXユーティリティの使用:
ノート:
ed
常に最初に入力ファイル全体をメモリに読み込みます。最初の行に直接追加するには(のように、入力ファイルが完全に空(バイト)sed
の場合、これは機能しません):0
ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
-s
抑制されed
たのステータスメッセージ。ed
複数行のヒアドキュメント(<<EOF\n...\nEOF
)として、つまりstdinを介してどのように提供されているかに注意してください。デフォルトでは、文字列展開はそのようなドキュメントで実行されます(シェル変数は補間されます)。それを抑制するために開始区切り文字を引用<<'EOF'
します(例:) 。1
1行目を現在の行にしますs
のように、現在の行で正規表現ベースの文字列置換を実行します。置換テキストにリテラル改行をsed
含めることができますが、エスケープする必要があります。\
w
結果を入力ファイルに書き戻します(テストの場合は、に置き換えw
て、入力ファイルを変更せずに結果,p
のみを印刷します)。1つ以上の行全体を追加するには:
と同様にsed
、このi
関数は常に、挿入されるテキストに末尾の改行を追加します。
ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
0 i
(ファイルの先頭)を0
現在の行にし、挿入モードを開始します(i
); 1
それ以外の場合、行番号はベースであることに注意してください。.
であり、独自の行で終了します。おそらく何も組み込まれていませんが、次のように簡単に自分で書くことができます。
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
少なくともそのようなもの...
を使用する別の方法sed
:
sed -i.old '1 {i to be prepended
}' inFile
付加する行が複数行の場合:
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile
解決:
printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt
拡張がないため、これはすべての種類の入力で安全であることに注意してください。たとえば、先頭に追加する場合は、次のよう!@#$%^&*()ugly text\n\t\n
に機能します。
printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt
検討のために残された最後の部分は、コマンド置換中のファイルの終わりでの空白の削除です"$(cat file.txt)"
。このためのすべての回避策は比較的複雑です。file.txtの最後に改行を保持する場合は、https ://stackoverflow.com/a/22607352/1091436を参照してください。
編集者注:
状況によっては、先頭に追加されたテキストはstdinからのみ入手できる場合があります。次に、この組み合わせが機能します。
echo "to be prepended" | cat - text.txt | tee text.txt
出力を省略したい場合はtee
、を追加して> /dev/null
ください。
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」の次の内容を受け取ります。
New Line
Original Line
中間ファイルはなく、bash/echoだけです。
もう1つのかなり簡単な解決策は次のとおりです。
$ echo -e "string\n" $(cat file)
あなたがvi/vimが好きなら、これはあなたのスタイルかもしれません。
printf '0i\n%s\n.\nwq\n' prepend-text | ed file
1行以上のテキスト(変数またはサブシェルコードを含む)を追加し、読みやすくフォーマットしたままにしておきたい将来の読者のために、これを楽しむことができます。
echo "Lonely string" > my-file.txt
次に実行します
cat <<EOF > my-file.txt
Hello, there!
$(cat my-file.txt)
EOF
の結果cat my-file.txt
:
Hello, there!
Lonely string
これは、の読み取りmy-file.txt
が最初にサブシェルで行われるために機能します。私は常にこのトリックを使用して、構成ファイル全体をコピーするのではなく、Dockerコンテナー内の構成ファイルに重要なルールを追加します。
% echo blaha > blaha
% echo fizz > fizz
% cat blaha fizz > buzz
% cat buzz
blaha
fizz
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim\n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo
関数を定義し、必要に応じてインポートして使用することをお勧めします。
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
}
次に、次のように使用します。
prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"
ファイルの内容は次のようになります。
This is second
This is first
このアプローチを使用して、変更ログアップデーターを実装しようとしています。
あなたはawkでそれを簡単に行うことができます
cat text.txt|awk '{print "to be prepended"$0}'