2016-09-03 84 views
1

我想用一個句號後面有一個空格替換一個CSV的標題場(場2)上了一個句號:用sed來代替句號與句號後面空間

CSV例如:

8389383, hello my.friend,839083083,3390903 

預期輸出:

8389383, hello my. friend,839083083,3390903 

我可以成功地取代了一個句號的CSV與空間只能用這條線:

sed -r ':b s/^([^,]*,[^,]*)\./\1 /g; t b' csv 

但是,我想用句號替換句號,後面跟一個空格。我試過了:

sed -r ':b s/^([^,]*,[^,]*)\./\1. /g; t b' csv 

但是這個掛起並且不會產生結果。

什麼可以添加到該行以允許這?

編輯 - 只需要添加,我想替換的字段2(標題字段)中可能會有多個句點。我也不希望這條規則適用於csv中的任何其他字段。

+0

不妨加樣品輸入/輸出,更好地反映您的要求,以便其他人可以輕鬆地測試:) – Sundeep

+3

一點也沒有不要停下來,因爲在完全停止之後還沒有完成數十億上千億的空間。當它第一次匹配時,它添加一個空白;這個測試是真實的,所以它回來了,再次嘗試,發現一個停止,增加一個空白,並且......在一段時間後它變得無聊。您可能需要在停止後留出一些尾隨上下文 - 非空白。 –

回答

5

awk是最適合這些類型的工作崗位

對於更換所有全停在第二場就

awk -v FS="," -v OFS="," '{gsub(/\./,". ",$2)}1' file.csv > tmpfile && mv tmpfile file.csv 

8389383, hello my. friend,839083083,3390903 
8389383, hello my. fri. end,839083083,3390903 
+2

awk在這裏似乎是最好的選擇,因爲我們可以有選擇地將'g'標誌應用於第二個字段 – Sundeep

+0

@spasic您是否指定了'gensub'。你可能知道'sub'和'gsub'都沒有。不過,使用'gensub'可以減少腳本的移植性。 – sjsam

+0

@sjsam好吧,這看起來可能會有所斬獲,但首先 - 我不太熟悉awk,它能以類似於'sed -i'的方式直接將結果呈現給文件嗎? – neilH

1

如何:

sed -i -e 's/^\([^,]*,[^.,]*\)\.\([^,]*\)/\1. \2/' file.csv 

編輯如果你在現場有多個句號,你不能sed做到這一點。這裏有一個perl一行代碼,但:

perl -i -pe 'sub t {($s)[email protected]_; $s=~s/\./. /g; $s}; s/^[^,]*,\K([^,]*)/t($1)/e;' file.csv 

說明:隨着s///命令,我們發現的第一個字段([^,]*,),我們跳過它(\K),然後我們找到第二個字段(([^,]*))。對於那個領域,我們執行功能t,它做一個簡單的變電站。

+0

嗨,這隻會取代這第一句句號。如果在第二個字段中有更多的字段,它似乎不會取代它們。 – neilH

+0

@ bms9nmh:使用'sed'確實很費力。 – sjsam

+0

@ bms9nmh對不起,我錯過了你編輯的問題。我爲我的答案添加了一個基於perl的解決方案。它不能用'sed'完成。 – redneb

0

這可能爲你工作(GNU SED):

sed -r ':a;s/^([^,]*,[^,.]*)\./\1\n/;ta;s/\n/. /g' file 

這裏的訣竅是把.變成something else(我贊成新因爲它通過seds設計是唯一的),然後全局更改something elsewhatever作爲線上的最後一個操作。

另一種方法是複製行,換一塊,並用重組從複製的部分,你不希望更改線路:

sed -r 's/,/\n/;s/,/\n/;h;s/\./& /g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2,\1,/' file 
0
$ cat file.csv 
8389383, hello my.friend, 839083083, 3390903 
8389383, hello my.fri.end, 839083083, 3390903 

$ perl -i -F, -e '$F[1] =~ s/\./. /g; print join(",",@F)' file.csv 

$ cat file.csv 
8389383, hello my. friend, 839083083, 3390903 
8389383, hello my. fri. end, 839083083, 3390903 
  • -F,分割每行在,並將其保存在@F陣列中。 -F選項也隱式設置爲-a-n。請參閱perldoc Command Switches以進一步閱讀
  • join(",",@F)將陣列與,一起作爲分隔符。不知道是否有Perl中的含蓄的方式來打印相同的輸入分隔符修改後的數組