Unix: ค้นหาและแทนที่เครื่องหมายจุลภาคที่ต่อเนื่องกันเป็นไปป์ไลน์ที่ต่อเนื่องกัน
ฉันกำลังแปลง CSV ที่ยกมาสองครั้งเป็นไฟล์ txt ที่คั่นด้วยไปป์ไลน์ใน Unix ฉันใช้คำสั่ง sed ต่อไปนี้เพื่อแทนที่ "," เป็น | จากนั้นลบเครื่องหมายคำพูดคู่เริ่มต้นและสิ้นสุด
sed -e 's/","/|/g' -e 's/"//g' filenm.csv > filenm.txt
แต่ดูเหมือนว่าไฟล์จะมีเครื่องหมายจุลภาคติดต่อกันโดยไม่มีเครื่องหมายอัญประกาศคู่และไม่มีการแทนที่
Col1|col2|col3|col4|col5|col6|col7|col8
Val1|val2|val3,,,,val7|val8
ตอนนี้ฉันต้องการแปลงเครื่องหมายจุลภาคต่อเนื่องกันทั้งหมดนี้เป็นไปป์ไลน์ที่ต่อเนื่องกันเนื่องจากระบุว่าช่องว่างหรือว่าง
และเขตข้อมูลอื่น ๆ ยังมีเครื่องหมายจุลภาคภายในค่าเขตข้อมูลซึ่งไม่ควรเปลี่ยนแปลง
ฉันลองใช้ด้านล่างสำหรับสิ่งนั้น แต่ไม่ได้ผล
sed -e 's/,{1,\}/|{1,\}/g' filenm.csv > filenm.txt
ไฟล์ csv ตัวอย่างที่เปิดใน 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"
ฉันหวังว่านี่จะช่วยทำให้ปัญหาเกิดซ้ำและแก้ไขได้
ขอบคุณล่วงหน้า....
คำตอบ
คุณสามารถใช้perl
:
perl -pe 's/"([^"]*)"|,/defined($1) ? $1 : "|"/ge' filenm.csv > filenm.txt
รายละเอียด :
"([^"]*)"|,
- รูปแบบนิพจน์ทั่วไปที่จับคู่"
จากนั้นจับเป็นกลุ่ม 1 อักขระใด ๆ ที่เป็นศูนย์หรือมากกว่านอกเหนือ"
จากนั้นจับคู่ a"
หรือจับคู่กับ,
ในบริบทอื่น ๆ ทั้งหมดdefined($1) ? $1 : "|"
- RHS การแทนที่ซึ่งแทนที่การจับคู่ด้วยค่ากลุ่ม 1 (ถ้าจับคู่กลุ่ม 1) หรือด้วย|
(ถ้า,
ตรงกัน)ge
-g
ย่อมาจากglobal
(แทนที่เหตุการณ์ทั้งหมด) และe
ทำให้ Perl ถือว่า RHS เป็นนิพจน์ Perl
ดูการทดสอบออนไลน์ :
#!/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"
เอาท์พุต:
ID|Name|DOB|Age|Address|City|State|Country|Phone number
123|ABC|12/20/2020|0|No.38,3rd st, RRR NNN, TRT||||9999999999
สิ่งนี้อาจได้ผลสำหรับคุณ (GNU sed):
sed -E ':a;s/^(("[^",]*",+)*"[^",]*),/\1\n/;ta;y/,\n/|,/' file
ซ้ำแทนที่,
's ระหว่าง"
' S กับการขึ้นบรรทัดใหม่แล้วแปล,
's สำหรับ|
' s และการขึ้นบรรทัดใหม่สำหรับ,
's
ใช้ awk:
awk -F \" '{ for(i=1;i<=NF;i++) { if ($i ~ /^[,]{2,}$/) { $i="," } } OFS="\"";gsub("\",\"","\"|\"",$0)}1' sample.csv
คำอธิบาย:
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
ฉันจะใช้ GNU AWK
สำหรับวิธีต่อไปนี้ ให้file.txt
เนื้อหาเป็น
"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"
แล้ว
awk 'BEGIN{FS="\"";OFS=""}{for(i=1;i<=NF;i+=2){$i=gensub(/,/,"|","g",$i)};print $0}' file.txt
เอาท์พุท
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
ฉันคิดว่าคอลัมน์แรกและคอลัมน์สุดท้ายจะไม่ว่างเปล่า ผมใช้"
เป็นตัวคั่นฟิลด์และจากนั้นในฟิลด์คี่ทุก (เหล่านี้มี แต่เพียงผู้เดียว,
) ฉันเปลี่ยนแปลงตลอดไป,
|
ในที่สุดฉันก็พิมพ์บรรทัดที่เปลี่ยนแปลงดังกล่าวทั้งหมด
(ทดสอบใน GNU Awk 5.0.1)