मैं निम्नलिखित CSV फ़ाइल का उपयोग करके sed
या कैसे कर सकता हूँ awk
?
- एक कॉलम हटाएं
- एक कॉलम डुप्लिकेट करें
- एक स्तंभ ले जाएँ
मेरे पास 200 से अधिक पंक्तियों के साथ एक बड़ी तालिका है, और मैं इससे परिचित नहीं हूं sed
।
मैं निम्नलिखित CSV फ़ाइल का उपयोग करके sed
या कैसे कर सकता हूँ awk
?
मेरे पास 200 से अधिक पंक्तियों के साथ एक बड़ी तालिका है, और मैं इससे परिचित नहीं हूं sed
।
जवाबों:
खेतों को कैसे काटें और फिर से व्यवस्थित करें (अन्य उत्तरों में कवर) के अलावा, quirky CSV फ़ील्ड का मुद्दा है।
यदि आपका डेटा इस "quirky" श्रेणी में आता है, तो पूर्व और पोस्ट फ़िल्टरिंग का थोड़ा ध्यान रखा जा सकता है। नीचे दिखाया गया फिल्टर की आवश्यकता होती है वर्ण \x01
, \x02
, \x03
, \x04
आपके डेटा में कहीं भी दिखाई नहीं करने के लिए।
यहाँ फिल्टर को साधारण awk
फ़ील्ड डंप के चारों ओर लपेटा गया है ।
नोट: फ़ील्ड-पाँच में एक अमान्य / अपूर्ण "उद्धृत फ़ील्ड" लेआउट है, लेकिन यह पंक्ति के अंत में (CSV पार्सर के आधार पर) सौम्य है। लेकिन, निश्चित रूप से, यह समस्याग्रस्त unexpedted परिणाम का कारण होगा अगर इसे अपने वर्तमान अंत पंक्ति स्थिति से दूर स्वैप किया जाना था ।
अद्यतन करें; जब एक अल्पविराम अनुगामी उद्धरण से पहले user121196 ने एक बग को इंगित किया है। यहाँ तय है।
आँकड़े
cat <<'EOF' >file
field one,"fie,ld,two",field"three","field,\",four","field,five
"15111 N. Hayden Rd., Ste 160,",""
EOF
कोड
sed -r 's/^/,/; s/\\"/\x01/g; s/,"([^"]*)"/,\x02\1\x03/g; s/,"/,\x02/; :MC; s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g; tMC; s/^,// ' file |
awk -F, '{ for(i=1; i<=NF; i++) printf "%s\n", $i; print NL}' |
sed -r 's/\x01/\\"/g; s/(\x02|\x03)/"/g; s/\x04/,/g'
उत्पादन:
field one
"fie,ld,two"
field"three"
"field,\",four"
"field,five
"15111 N. Hayden Rd., Ste 160,"
""
यहाँ पूर्व फ़िल्टर है , टिप्पणियों के साथ विस्तारित किया गया है। पोस्ट फिल्टर बस के विपरीत है । , ,\x01
\x02
\x03
\x04
sed -r '
s/^/,/ # add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/ # when no trailing quote on last field
:MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter
'
यह इस बात पर निर्भर करता है कि क्या आपका CSV फ़ाइल केवल सीमांकक का उपयोग करता है, या यदि आपके पास पागलपन है:
फ़ील्ड एक, "फ़ील्ड, दो", फ़ील्ड तीन
यह मानता है कि आप एक सरल CSV फ़ाइल का उपयोग कर रहे हैं:
आप एकल कॉलम से कई तरह से छुटकारा पा सकते हैं; मैंने उदाहरण के रूप में कॉलम 2 का उपयोग किया। सबसे आसान तरीका संभवतः उपयोग करना है cut
, जो आपको एक सीमांकक निर्दिष्ट करता है -d
और आप किन क्षेत्रों को प्रिंट करना चाहते हैं -f
; यह इसे कॉमा और आउटपुट फ़ील्ड 1 पर विभाजित करने के लिए कहता है, और फ़ील्ड 3 अंत के माध्यम से:
$ cut -d, -f1,3- /path/to/your/file
यदि आपको वास्तव में उपयोग करने की आवश्यकता है sed
, तो आप एक नियमित अभिव्यक्ति लिख सकते हैं जो पहले n-1
क्षेत्रों, n
वें क्षेत्र और बाकी से मेल खाती है , और n
वें को आउटपुट करना छोड़ें (यहां n
2 है, इसलिए पहले समूह का मिलान 1
समय पर किया जाता है:) \{1\}
:
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/' /path/to/your/file
ऐसा करने के कई तरीके हैं awk
, उनमें से कोई भी विशेष रूप से सुरुचिपूर्ण नहीं है। आप एक for
लूप का उपयोग कर सकते हैं , लेकिन अनुगामी अल्पविराम से निपटना एक दर्द है; यह देखते हुए कि यह कुछ इस तरह होगा:
$ awk -F, '{for(i=1; i<=NF; i++) if(i != 2) printf "%s,", $i; print NL}' /path/to/your/file
मुझे फ़ील्ड 1 आउटपुट करना आसान लगता है और फिर substr
फ़ील्ड 2 के बाद सब कुछ बंद करने के लिए उपयोग करना चाहिए:
$ awk -F, '{print $1 "," substr($0, length($1)+length($2)+3)}' /path/to/your/file
यह हालांकि आगे स्तंभों के लिए कष्टप्रद है
इसमें sed
अनिवार्य रूप से पहले की तरह ही अभिव्यक्ति होती है, लेकिन आप लक्ष्य स्तंभ पर भी कब्जा कर लेते हैं और उस समूह को प्रतिस्थापन में कई बार शामिल करते हैं:
$ sed 's/\(\([^,]\+,\)\{1\}\)\([^,]\+,\)\(.*\)/\1\3\3\4/' /path/to/your/file
में awk
पाश रास्ता के लिए यह कैसा (फिर अनुगामी अल्पविराम अनदेखी) कुछ हो जाएगा:
$ awk -F, '{
for(i=1; i<=NF; i++) {
if(i == 2) printf "%s,", $i;
printf "%s,", $i
}
print NL
}' /path/to/your/file
जिस substr
तरह से:
$ awk -F, '{print $1 "," $2 "," substr($0, length($1)+2)}' /path/to/your/file
(tcdyl उनके जवाब में एक बेहतर विधि के साथ आया )
मुझे लगता है कि sed
समाधान दूसरों से स्वाभाविक रूप से अनुसरण करता है, लेकिन यह हास्यास्पद रूप से लंबा होना शुरू हो जाता है
awk
तुम्हारा सबसे अच्छा दांव है। awk
खेतों को संख्या से प्रिंट करता है, इसलिए ...
awk 'BEGIN { FS=","; OFS=","; } {print $1,$2,$3}' file
किसी कॉलम को निकालने के लिए, उसे प्रिंट न करें:
awk 'BEGIN { FS=","; OFS=","; } {print $1,$3}' file
आदेश बदलने के लिए:
awk 'BEGIN { FS=","; OFS=","; } {print $3,$1,$2}' file
आउटपुट फ़ाइल पर फिर से निर्देशित करें।
awk 'BEGIN { FS=","; OFS=","; } {print $3,$1,$2}' file > output.file
awk
आउटपुट को भी प्रारूपित कर सकते हैं।
निम्नलिखित प्रारूप में एक स्थान-सीमांकित फ़ाइल को देखते हुए:
1 2 3 4 5
आप फ़ील्ड 2 को awk जैसे हटा सकते हैं:
awk '{ sub($2,""); print}' file
जो लौटता है
1 3 4 5
कॉलम 2 को कॉलम n से बदलें जहाँ उपयुक्त हो।
कॉलम 2 को डुप्लिकेट करने के लिए,
awk '{ col = $2 " " $2; $2 = col; print }' file
जो लौटता है
1 2 2 3 4 5
कॉलम 2 और 3 को स्विच करने के लिए,
awk '{temp = $2; $2 = $3; $3 = temp; print}'
जो लौटता है
1 3 2 4 5
awk आमतौर पर खेतों की अवधारणा से निपटने में बहुत अच्छा है । यदि आप CSV के साथ काम कर रहे हैं, और स्पेस-सीमांकित फ़ाइल नहीं है, तो आप बस उपयोग कर सकते हैं
awk -F,
अपने क्षेत्र को अल्पविराम के रूप में परिभाषित करने के लिए, स्थान के बजाय (जो डिफ़ॉल्ट है)। ऑनलाइन कई अच्छे awk संसाधन हैं, जिनमें से एक को मैं नीचे दिए गए स्रोत के रूप में सूचीबद्ध करता हूं।
# 3 के लिए स्रोत
awk
, लेकिन यह उत्पादन करने लगता है अंतरिक्ष से अलग की गई है, भले ही क्षेत्र विभाजक है ,
(क्षेत्र-विभाजक बस नियंत्रण कैसे यह इनपुट के प्रबंधन)
यह हटाने के लिए काम करेगा
awk '{$2="";$0=$0;$1=$1}1'
इनपुट
a b c d
उत्पादन
a c d