Unix: Tìm và thay thế các dấu phẩy liên tiếp thành các đường ống liên tiếp
Tôi đang chuyển đổi một CSV được trích dẫn kép thành tệp txt được phân cách bằng đường ống trong Unix. Tôi đã sử dụng lệnh sed sau để thay thế "," thành | sau đó loại bỏ dấu ngoặc kép bắt đầu và kết thúc.
sed -e 's/","/|/g' -e 's/"//g' filenm.csv > filenm.txt
Nhưng tệp dường như có các dấu phẩy liên tiếp không có dấu ngoặc kép và chúng sẽ không bị thay thế.
Col1|col2|col3|col4|col5|col6|col7|col8
Val1|val2|val3,,,,val7|val8
Bây giờ tôi muốn chuyển đổi tất cả các dấu phẩy liên tiếp này thành các đường ống liên tiếp vì chúng chỉ ra các trường trống hoặc rỗng.
Và các trường khác cũng có dấu phẩy bên trong các giá trị trường không được thay đổi.
Tôi đã thử sử dụng bên dưới cho điều đó, nhưng không hoạt động.
sed -e 's/,{1,\}/|{1,\}/g' filenm.csv > filenm.txt
tệp csv mẫu được mở trong notepad:
"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","15","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
"456","DEF","12/20/2020",,,,,"test-country","9999999999"
"465","XYZ",,,"No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
Tôi hy vọng điều này sẽ giúp tái tạo vấn đề và giải quyết.
Cảm ơn trước....
Trả lời
Bạn có thể sử dụng perl
:
perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' filenm.csv > filenm.txt
Chi tiết :
"([^"]*)"|,
- mẫu regex khớp"
, sau đó ghi vào Nhóm 1 bất kỳ ký tự nào không hoặc nhiều ký tự khác"
và sau đó khớp với a"
hoặc chỉ khớp với a,
trong tất cả các ngữ cảnh khácdefined($1) ? $1 : "|"
- RHS, thay thế, thay thế trận đấu bằng giá trị Nhóm 1 (nếu Nhóm 1 đã được khớp) hoặc bằng một|
(nếu giá trị,
đã được khớp)ge
-g
là viết tắt củaglobal
(thay thế tất cả các lần xuất hiện) vàe
làm cho Perl coi RHS như một biểu thức Perl.
Xem một bài kiểm tra trực tuyến :
#!/bin/bash
s='"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","0","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"'
perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' <<< "$s"
Đầu ra:
ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|0|No.38,3rd st, RRR NNN, TRT||||9999999999
Điều này có thể phù hợp với bạn (GNU sed):
sed -E ':a;s/^(("[^",]*",+)*"[^",]*),/\1\n/;ta;y/,\n/|,/' file
Lặp lại thay thế ,
's between "
' bằng các dòng mới, sau đó dịch ,
's for |
' và dòng mới cho ,
's.
Sử dụng awk:
awk -F \" '{ for(i=1;i<=NF;i++) { if ($i ~ /^[,]{2,}$/) { $i="," } } OFS="\"";gsub("\",\"","\"|\"",$0)}1' sample.csv
Giải trình:
awk -F \" '{ # Set the field delimiter to double quote
for(i=1;i<=NF;i++) {
if ($i ~ /^[,]{2,}$/) {
$i="," # Loop through each field and if is contains 2 or more commas, set that field to one comma } } OFS="\""; gsub("\",\"","\"|\"",$0) # Substitute "," for "|"
}1' sample.csv
Tôi sẽ sử dụng GNU AWK
cho cách sau. Hãy để file.txt
nội dung
"ID","Name","DOB","Age","Address","City","State","Country","Phone number"
"123","ABC","12/20/2020","15","No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
"456","DEF","12/20/2020",,,,,"test-country","9999999999"
"465","XYZ",,,"No.38,3rd st, RRR NNN, TRT",,,,"9999999999"
sau đó
awk 'BEGIN{FS="\"";OFS=""}{for(i=1;i<=NF;i+=2){$i=gensub(/,/,"|","g",$i)};print $0}' file.txt
đầu ra
ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|15|No.38,3rd st, RRR NNN, TRT||||9999999999
456|DEF|12/20/2020|||||test-country|9999999999
465|XYZ|||No.38,3rd st, RRR NNN, TRT||||9999999999
Tôi giả định rằng cột đầu tiên và cột cuối cùng không bao giờ trống. Tôi sử dụng "
làm dấu phân tách trường và sau đó trong mọi trường lẻ (chỉ chứa các trường này ,
), tôi thay đổi tất cả ,
thành |
. Cuối cùng tôi in toàn bộ dòng đã thay đổi như vậy.
(được thử nghiệm trong GNU Awk 5.0.1)