テキストファイルに文字列データを付加するUnixコマンドはありますか?
何かのようなもの:
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
テキストファイルに文字列データを付加するUnixコマンドはありますか?
何かのようなもの:
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
回答:
sed -i.old '1s;^;to be prepended;' inFile
-i
変更を適切に書き込み、拡張子が指定されている場合はバックアップを取ります。(この場合、.old
)1s;^;to be prepended;
;
コマンドの区切り文字として使用して、最初の行の先頭を指定された置換文字列で置き換えます。\n
先頭に追加したい場合があります。彼らのニーズに応じて。きちんとしたソリューション。
inFile
パスにディレクトリを含めることはできますか?
\n
。最初にコメントを読むべきだった。くそー。
'1s;^;my-prepended-line\;\n;'
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
git config --get-regex $arg | sed -r 's/\t{3}/\\n/g';
ましたが、\t
とを変換するときにこれがめちゃくちゃになり\n
ます。
echo "to be prepended"$'\n'"$(cat text.txt)"
誰もこれに言及しなかったのには驚きです。
cat <(echo "before") text.txt > newfile.txt
これは、受け入れられた回答よりも間違いなく自然です(何かを出力して置換コマンドにパイプすることは、辞書式順序的に直観に反しています)。
...そして、ライアンが上で言ったことをハイジャックしsponge
ます、あなたは一時ファイルを必要としません:
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
編集:これはボーンシェルでは機能しないようです /bin/sh
here-string-を使用すると<<<
、次のことができます。
<<< "to be prepended" < text.txt | sponge text.txt
<<(echo "to be prepended") < text.txt
と<<< "to be prepended" < text.txt
の構成は、bashで動作しません。zshが必要です。
これは1つの可能性です。
(echo "to be prepended"; cat text.txt) > newfile.txt
おそらく、中間ファイルを簡単に回避することはできません。
代替案(シェルエスケープでは煩雑になる場合があります):
sed -i '0,/^/s//to be prepended/' text.txt
cat <(echo "to be prepended") text.txt > newfile.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
text.txt
、要求に応じてテキストをファイルの先頭に追加しませんが、標準出力に表示します。OPで機能する場合は、出力を別のファイルにまとめることができます
注意:
これを行うと、予期しない副作用が発生する可能性があります。特に、シンボリックリンクを通常のファイルに置き換えたり、ファイルに対するさまざまな権限を取得したり、ファイルの作成(生)日付を変更したりする可能性があります。
sed -i
、Prince John Wesleyの回答のように、少なくとも元の権限を復元しようとしますが、他の制限も適用されます。
一時ファイルを使用する簡単な代替方法を次に示します(shimeのソリューションのように、入力ファイル全体をメモリに読み込むのを避けます)。
{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
使用グループコマンドは({ ...; ...; }
)を使用して、よりわずかに効率的であるサブシェルを((...; ...)
と)0xC0000022Lの溶液。
利点は次のとおりです。
新しいテキストを最初の行に直接追加するか、新しい行として挿入するか(単に引数に追加\n
するprintf
か)を制御するのは簡単です。
sed
ソリューションとは異なり、入力ファイルが空(0
バイト)の場合に機能します。
sed
溶液は意図は、1つまたは複数の前に付加する場合を簡略化することができる全体の行を(入力ファイルが空であると仮定して)既存のコンテンツに:
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
複数行のhere-document(<<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
MAKES 0
(ファイルの先頭)モード、インサート現在の行と開始(i
); それ以外の場合は行番号が1
ベースになることに注意してください。.
ます。おそらく何も組み込まれていませんが、次のようにして自分で簡単に作成できます。
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
少なくともそのような何か...
$$
ただし、本番用コードでは使用は不十分です(グーグルsymlink攻撃)。しかし、それは確かに静的ファイル名よりも優れています。
mktemp
状況によっては、先頭に追加されたテキストはstdinからしか利用できない場合があります。次に、この組み合わせが機能します。
echo "to be prepended" | cat - text.txt | tee text.txt
tee
出力を省略したい場合は、を追加します> /dev/null
。
tee
破壊されないという保証はありますか?私はそうは思いません—これはこの解決策をファイルの健康にとって危険にするでしょう。text.txt
cat
lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null
。場合はlenA
1000000(1MBのファイル)で、lenB
10000(10KBテキストプリペンド)で、そのファイル「A.TXT」は「B」の文字の20KBで上書きされます。これは完全に壊れています。ここで、1Mb a.txtと1Mbテキストを使用して先頭に追加し、tee
7Gb +ファイルを生成するループに入る場合、コマンドを停止する必要がありました。したがって、サイズが大きい場合の結果は予測できないことは明らかです。小さいサイズでも動作するかどうかはわかりません。
解決:
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
file.txt
への引数リストに適合できるよりも大きい場合に発生しprintf
ます。
別の使用方法sed
:
sed -i.old '1 {i to be prepended
}' inFile
先頭に追加する行が複数行の場合:
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile
sed -i '1ito be prepended' inFile
ですか?それともGNU sedでのみ許可されているのですか?
sed
では、i
コマンドの後にバックスラッシュと改行が続き、最後の行を除く各入力行もバックスラッシュで終わります。GNU sed
はあなたが尋ねる行に沿った省略表現を許可しますが、そうするのはGNUだけsed
です。
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のみです。
別のかなり簡単な解決策は次のとおりです。
$ echo -e "string\n" $(cat file)
cat
二重引用符でパラメーターを展開しないことは、反対票を投じる十分な理由です。このコードは、ファイルの内容を単語に分割し、それらの各単語を個別の引数としてに渡しますecho
。あなたは、元の引数の境界を失い、あなたは改行/タブの/ etc。失う、とのような文字列\t
と\n
、元のテキストでは、タブ、改行の代わりに、彼らがいたとして保持された状態で置き換えられます。
関数を定義してから、必要に応じてインポートして使用することをお勧めします。
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
このアプローチを使用して、変更ログのアップデーターを実装しようとしています。