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

Jan 08 2021

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

2 WiktorStribiżew Jan 08 2021 at 22:37

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ác
  • defined($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- glà viết tắt của global(thay thế tất cả các lần xuất hiện) và elà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
4 potong Jan 08 2021 at 23:05

Đ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.

1 RamanSailopal Jan 09 2021 at 00:35

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
1 Daweo Jan 09 2021 at 01:50

Tôi sẽ sử dụng GNU AWKcho cách sau. Hãy để file.txtnộ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)