यूनिक्स: लगातार पाइपलाइनों के लिए लगातार अल्पविराम खोजें और बदलें
मैं यूनिक्स में सीमांकित txt फ़ाइल को पाइपलाइन करने के लिए एक डबल उद्धृत CSV परिवर्तित कर रहा हूं। मैंने "," को बदलने के लिए निम्नलिखित 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
नमूना सीएसवी फ़ाइल नोटपैड में खोली गई:
"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 में किसी भी शून्य या अधिक वर्णों के अलावा किसी"
और से मेल खाता है"
या फिर,
अन्य सभी संदर्भों में मेल खाता हैdefined($1) ? $1 : "|"
- RHS, प्रतिस्थापन, जो मैच को समूह 1 मान (यदि समूह 1 का मिलान किया गया था) के साथ या|
(यदि,
मिलान किया गया था) के साथ बदल देता हैge
- (सभी घटनाओं की जगह)g
के लिए खड़ा हैglobal
औरe
पर्ल को आरएचएस को पर्ल अभिव्यक्ति के रूप में मानता है।
एक ऑनलाइन परीक्षा देखें :
#!/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
Iteratively की नई सुर्खियों के ,
बीच "
की जगह है, तो अनुवाद ,
के लिए है |
और नई के लिए है ,
।
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
मैं AWK
उस तरीके के लिए GNU का उपयोग करूंगा । 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 में परीक्षण किया गया)