यूनिक्स: लगातार पाइपलाइनों के लिए लगातार अल्पविराम खोजें और बदलें

Jan 08 2021

मैं यूनिक्स में सीमांकित 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"

मुझे उम्मीद है कि इस मुद्दे को सुलझाने और हल करने में मदद मिलेगी।

अग्रिम में धन्यवाद....

जवाब

2 WiktorStribiżew Jan 08 2021 at 22:37

आप उपयोग कर सकते हैं 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
4 potong Jan 08 2021 at 23:05

यह आपके लिए काम कर सकता है (GNU sed):

sed -E ':a;s/^(("[^",]*",+)*"[^",]*),/\1\n/;ta;y/,\n/|,/' file

Iteratively की नई सुर्खियों के ,बीच "की जगह है, तो अनुवाद ,के लिए है |और नई के लिए है ,

1 RamanSailopal Jan 09 2021 at 00:35

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

मैं 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 में परीक्षण किया गया)