web-dev-qa-db-ja.com

「カット」でファイルを変更できますか?

man page はあまり期待できませんが、ドキュメント化されていない(またはGNU固有の)機能であることを願っています。

17
Hank Gay

できません。 edまたはGNU sedまたはPerlを使用するか、コンテンツの新しいファイルを作成するために裏で行うことを行います。

ed、ポータブル:

ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF

GNU sed

sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo

Perl:

Perl -i -l -F, -pae 'print @F[1,3]' foo

cut、新しいファイルを作成します(スクリプトが中断された場合は、もう一度実行することができるため、推奨されます):

cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo

cut、ファイルを所定の場所に置き換えます(fooの所有権と権限は保持しますが、中断に対する保護が必要です):

cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old

cutベースのメソッドのいずれかを使用することをお勧めします。そうすれば、非標準のツールに依存せず、ジ​​ョブに最適なツールを使用でき、割り込み時の動作を制御できます。

Ubuntuの moreutils パッケージ(および debian )にはspongeというプログラムがあり、これによって問題も解決されます。

男のスポンジから:

スポンジは標準入力を読み取り、それを指定されたファイルに書き込みます。シェルリダイレクトとは異なり、スポンジは出力ファイルを開く前にすべての入力を吸収します。これにより、同じファイルの読み取りと書き込みを行うパイプラインを制限できます。

次のようなことができます:

cut -d <delim> -f <fields> somefile | sponge somefile
25

cutだけではそれは不可能だと思います。 manページやinfoページでは見つかりませんでした。次のようなことができます

mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file

mktempを使用すると、cut出力をパイプ処理できる比較的安全な一時ファイルになります。

9
Steven D

Vim-wayを試してください:

$ ex -s +'%!cut -c 1-10' -cxa file.txt

これにより、ファイルがインプレースで編集されます(最初にバックアップを行ってください)。

または、 grepsed または gawk を使用します。

1
kenorb

SlurpをPOSIX Awkで使用できます。

cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file

0
Steven Penny

まあ、cutは読み取りよりも出力が少ないので、次のことができます。

cut -c1 < file 1<> file

つまり、そのstdinをfileを読み取り専用モードで開き、その標準出力をfileを読み取り+書き込みモードで切り捨てずに開く(<>)にします。

このようにして、cutはファイル自体を上書きします。ただし、ファイルの残りの部分は変更されません。たとえば、fileに次のものが含まれている場合:

foo
bar

出力は次のようになります。

f
b
bar

f\nb\nfoo\nを置き換えましたが、barはまだ残っています。 cutが終了したら、ファイルを切り捨てる必要があります。

ksh93を使用すると、<>;演算子と同じように機能する<>演算子を使用できます。ただし、コマンドが成功した場合、ftruncate()がファイル記述子で呼び出されます。そう:

cut -c1 < file 1<>; file

他のシェルでは、次のような他の方法でftruncate()を実行する必要があります。

{ cut -c1 < file; Perl -e 'truncate STDOUT, tell STDOUT';} 1<> file

ただし、そのためにPerlを呼び出すのは、特にPerlcutのような仕事を簡単に実行できることを考えると、ここでは少しやりすぎです。

Perl -pi -e '$_ = substr($_, 0, 1)' file

実際のインプレース書き換えを含むすべての方法で、操作が途中で中断されると、ファイルが破損することに注意してください。一時的な2番目のファイルを使用すると、この問題を回避できます。

0