25

私はCSVを持っています。CSV の 35 番目のフィールドを編集し、変更を 35 番目のフィールドに書き戻したい。これは私がbashでやっていることです:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g'

そのため、awk を使用して 35 番目のエントリを取得し、文字列の開始位置の「0」を「+91」に置き換えています。これは完璧に機能し、コンソールに目的の出力が表示されます。

ここで、この新しいエントリをファイルに書き込みたいと思います。sed の「インプレース」置換機能を考えていますが、この機能には入力ファイルが必要です。上記のコマンドでは、プライマリ コマンドが awk であり、sed が awk から入力を取得しているため、入力ファイルを提供できません。

ありがとう。

4

6 に答える 6

47

2 つのツールのいずれかを選択する必要があります。に関してはsed、次のように実行できます。

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv 

についてはわかりませんawkが、@shellter のコメントが役立つかもしれません。

于 2012-06-21T12:48:27.110 に答える
16

in-placesedの機能は、ファイルをその場で編集しないため、名前が間違っています。代わりに、同じ名前で新しいファイルを作成します。例えば:

$ echo foo > foo
$ ln -f foo bar
$ ls -i foo bar  # These are the same file
797325 bar  797325 foo
$ echo new-text > foo  # Changes bar
$ cat bar
new-text
$ printf '/new/s//newer\nw\nq\n' | ed foo  # Edit foo "in-place"; changes bar
9
newer-text
11
$ cat bar
newer-text
$ ls -i foo bar  # Still the same file
797325 bar  797325 foo
$ sed -i s/new/newer/ foo   # Does not edit in-place; creates a new file
$ ls -i foo bar
797325 bar  792722 foo    

sed は実際にはファイルをその場で編集しているのではなく、新しいファイルを書き込んでから古いファイルに名前を変更しているため、同じことを行うこともできます。

awk ... test.csv | sed ... > test.csv.1 && mv test.csv.1 test.csv

を使用sed -iすると一時ファイルの作成が回避されるという誤解があります。そうではありません。事実を隠しているだけです。抽象化は良いこともあれば、不必要な難読化になることもあります。の場合はsed -i後者です。シェルはファイル操作が得意です。意図したとおりに使用してください。ファイルをその場で編集する必要がある場合は、ストリーミング バージョンの を使用しないでくださいed。ただ使うed

于 2012-06-21T15:14:35.767 に答える
2

これはあなたのために働くかもしれません:

sed -i 's/[^,]*/+91/35' test.csv

編集:

35番目のフィールドの先行ゼロを置き換えるには:

sed 'h;s/[^,]*/\n&/35;/\n0/!{x;b};s//+91/' test.csv

またはもっと簡単に:

|sed 's/^\(\([^,]*,\)\{34\}\)0/\1+91/' test.csv
于 2012-06-21T16:39:31.803 に答える
2

したがって、それを行うには多くの方法があることがわかりました。以下のようにsedで動作させました:

sed -i 's/0\([0-9]\{10\}\)/\+91\1/g' test.csv

ただし、条件に一致するすべてのエントリを編集するため、これは少し注意が必要です。ただし、私の場合、正常に動作しています。

perl での上記のロジックの同様の実装:

perl -p -i -e 's/\b0(\d{10})\b/\+91$1/g;' test.csv

繰り返しますが、上記と同じ注意事項です。

Lev Levitskyによって示されているより正確な方法は 、35 フィールドで具体的に動作するためです

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/g' test.csv

より複雑な状況では、perl の csv モジュールのいずれかを使用することを検討する必要があります。

お時間とご意見をお寄せいただきありがとうございます。あなたの返信を読んだ後、私は確かにsed/awkについてもっと知っています。

于 2012-06-22T08:46:08.967 に答える
0

moreutilsがインストールされている場合は、次のspongeツールを簡単に使用できます。

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g' | sponge test.csv

sponge入力を吸収し、入力パイプ (stdin) を閉じてから、test.csvファイルを開いて書き込みます。

2015 年現在、moreutils は、Arch LinuxDebianUbuntuなど、いくつかの主要な Linux ディストリビューションのパッケージ リポジトリで利用できます。

于 2015-05-21T13:21:26.023 に答える