當我使用 csv 時,不需要的逗號(',')會誤導我的 csv 文件,導致不一致。
請在下面詳細了解。
我的範例 csv 檔案:
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
我想要的最終結果為:
1|"a,b"|4
1|"c,d"|4
1|"e,f"|4
1|"g,h"|4
1|"i,j"|4
添加引號後,我將替換“|”與“,”這樣我的csv將按我的預期工作。
我使用了下面的命令,但它沒有按預期給出。
sed -e 's/,/"&"/' file1.txt
答案1
使用csvformat
來自csvkit
,並假設最終結果應該是一個以逗號作為分隔符號的 CSV 檔案(如問題文本中所述):
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
這會將 CSV 檔案的格式從使用|
- 字元作為分隔符號重新設定為使用預設逗號作為分隔符號。這樣做時,它正確地引用了需要引用的欄位。
這也可以正確處理帶有嵌入換行符的欄位:
$ cat file
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
2|"line 1,
line2"|5
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
2,"line 1,
line2",5
如果您有某種結構化文檔格式的文檔,例如 CSV、JSON、XML、YAML、TOML 等,則沒有理由不是使用該文件格式的解析器來解析該文件。
答案2
你可以這樣做:
awk -F'[|]' -v OFS=',' -v q='"' '{ for(i=1; i<=NF; i++) $i=q $i q }1' infile
我們-F'[|]'
定義了輸入欄位分隔符號。
我們-v OFS=','
定義了輸出欄位分隔符號。
NF
根據 FS(輸入字段分隔符號)確定每行/記錄中有多少個字段,因此我們循環遍歷字段數並為每個字段添加雙引號,並在該行上列印最終更新awk 的1
習慣用法用於列印。
請注意,所有欄位都被此命令引用,這顯然對於擁有有效的 CSV 檔案來說不是問題。
答案3
和sed
:
$ sed 's/[^|]*,[^|]*/"&"/g; y/|/,/' ip.txt
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
s/[^|]*,[^|]*/"&"/g
將雙引號添加到包含以下內容的所有字段,
y/|/,/
將所有|
字元變更為,
和perl
:
perl -F'\|' -lane 'print join ",", map {/,/ ? qq("$_") : $_} @F'
這用作|
輸入欄位分隔符號。然後map
將為所有包含 的字段添加雙引號,
。最後,join
用於將字段與,
字元組合起來。
答案4
其他sed
方式:
sed 's;\([^|]*\)|\([^|]*\)|\(.*\)$;\1,"\2",\3;' data
或者,如果您sed
支援加載ERE
,例如GNU sed
,您可以避免所有轉義作業:
sed -E 's;([^|]+)\|([^|]+)\|(.+)$;\1,"\2",\3;' data
您可以利用這樣一個事實,即只有中間組|
在每個邊界處由 a 分隔,並使長度變得sed
更短:
sed 's;|\([^|]*\)|;,"\1",;' data
當然也在這裡,如果您的 sed 支持,-E
您可以加載ERE
並避免繁瑣的轉義工作