जागरण का उपयोग करके स्तंभों को पुन: व्यवस्थित करना


13

मैं अपने csv फ़ाइल के 7 वें कॉलम को उपयोग करके अंत में स्थानांतरित करने का प्रयास कर रहा हूं

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

जहाँ $ फ़ाइल एक निर्देशिका में .csv फ़ाइल है। हालाँकि, आउटपुट है

awk:                          ^ syntax error

क्या किसी को पता है कि इस त्रुटि को कैसे ठीक किया जाए?


7
अजीब त्रुटियों को दिखाते समय, आपको पूरी बात दिखाने की आवश्यकता है। ^आदेश जहां त्रुटि आई थी की विशिष्ट भाग इंगित करता है।
terdon

जवाबों:


11

-Fविकल्प एक बहस की जरूरत है: -F,उदाहरण के लिए।

awkस्क्रिप्ट का अंत बाकी मापदंडों के साथ (स्पेस चार) के साथ अलग किया जाना चाहिए ।

यदि फ़ील्ड विभाजक है ,और आप इसे रखना चाहते हैं, और यदि स्तंभ की संख्या स्थिर और 11 के बराबर या उससे कम है, तो इसके लिए प्रयास करें:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"

8
@anuribs बहुत कम प्रोग्राम इसकी अनुमति देते हैं। मानक तरीका है command file > newfile && mv newfile file। कहा कि, awkइस का समर्थन करने के लिए GNU का नया संस्करण gawk -i inplace '{blah blah}' file:।
terdon

1
वैकल्पिक रूप से, इसके बजाय mv newfile fileआप उपयोग कर सकते हैं cat newfile > file ; rm -f newfile- यह इनोड और अनुमतियों को सुरक्षित रखता है file
कैस

और यह आमतौर mktempपर स्क्रिप्ट में हार्ड-फाइलिंग अस्थायी फ़ाइलनाम के बजाय उपयोग करने के लिए एक अच्छा विचार है । जैसेtf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
कैस

8

छोटा समाधान होगा

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

मुझे यकीन नहीं है कि ,+सभी awkसंस्करणों में काम करेगा , लेकिन कम से कम GNU awk में काम करता है, वह भी -compatibility मोड के साथ ।

स्पष्टीकरण:

  • $(NF+1)=$7: पहले हम लाइन के अंत में 7 वां क्षेत्र जोड़ते हैं ( $12=$7इस मामले में हो सकता है)
  • $7="": अगले चरण में 7 वें क्षेत्र को मिटा दिया जाता है (लेकिन आसपास के सीमांकक रहने पर)
  • सीमांकक को हटाने के लिए हमें पूरे रिकॉर्ड (फिर से $0=$0) को अलग-अलग क्षेत्र के रूप में कई अल्पविरामों का इलाज करते हुए सेट करना होगा (यह इसके माध्यम से किया जाता है -F',+', यहां +एक या अधिक बार इसका मतलब है), और वर्तमान रिकॉर्ड को पुनर्व्यवस्थित $1=$1करके पूर्व निर्धारित आउटपुट फ़ील्ड का उपयोग करके लाइन के पुनर्निर्माण के लिए मजबूर करना विभाजक (एक विकल्प द्वारा निर्धारित -v OFS=,)
  • सभी फेरबदल के बाद हम परिणाम को प्रिंट करने के लिए तैयार हैं 1

उदाहरण इनपुट:

1,2,3,4,5,6,7,8,9,10,11

उत्पादन

1,2,3,4,5,6,8,9,10,11,7

यदि अन्य कॉलम रिक्त हैं तो क्या होगा? लेकिन, हाँ, एफएस POSIX में एक नियमित अभिव्यक्ति है (यदि यह कई अक्षर है), तो ,+काम करना चाहिए।
रैंडम 832

(1) मैं समझता हूं कि इनपुट डेटा के सातवें कॉलम को "गायब" करना, और न केवल इसे शून्य करना है, इस समस्या का एक मुश्किल हिस्सा है। लेकिन, जैसा कि रैंडम 832 कहता है, आपका समाधान रिक्त कॉलम (उदाहरण के लिए, all,ball,call,,,fallall,ball,call,fall) को क्लोब करता है । (२)  $(NF+1)=$7चतुर दृष्टिकोण है। IMHO, $0 = $0 OFS $7थोड़ा स्पष्ट है, केवल कुछ वर्ण लंबे हैं, और ऐसा ही लगता है। क्या आप ऐसी स्थिति के बारे में सोच सकते हैं जिसमें $0 = $0 OFS $7आपका कोड जैसा नहीं है?
जी-मैन का कहना है कि 'मोनिका'

@ Random832 @ जी-मैन हाँ, कुछ किनारे के मामले जैसे रिक्त क्षेत्र, रिक्त लाइनें या NF <7 को अलग से इलाज किया जाना चाहिए या किसी को कोड को फिर से व्यवस्थित करना चाहिए। यह केवल एक विचार है, सभी सामान्य मामलों के लिए "पूर्ण समाधान" नहीं, यह स्पष्ट होना चाहिए। $0=$0 OFS $7शायद समान है $(NF+1)=$7, लेकिन केवल शेष कोड अपरिवर्तित है, सामान्य रूप से नहीं।
jimmij

5

यदि आप के साथ मुद्रण कर रहे हैं OFS=, तो खेतों के बीच कोई विभाजक नहीं है, तो आप बस $7एक चर में मान को बचा सकते हैं , $7खाली और रेखा और चर को सीधे प्रिंट कर सकते हैं। आपको सभी फ़ील्ड निर्दिष्ट करने की आवश्यकता नहीं है:

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687

3

आप शायद मतलब है:

awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"

आप जानते हैं कि awkकभी भी एकल उद्धरण नहीं देखता है OFS='', है ना? आप बस टाइप कर सकते हैं OFS=; यह बिल्कुल वैसा ही है।
वाइल्डकार्ड

1
हां, मुझे एहसास है कि हालाँकि, मैं लटकते असाइनमेंट को नापसंद करता हूं।
माइकल व्हील्स


3

आपने विशेष रूप से यह नहीं कहा कि आप awk का उपयोग करना चाहते हैं, और आपने कहा था कि आप इन-प्लेस एडिटिंग का उपयोग करना चाहते हैं sed -i, जैसे कि यहाँ एक sed -iसंस्करण है। आमतौर पर awkकॉलम के साथ काम करने के लिए बेहतर है, लेकिन यह एक ऐसा मामला है जहां मैं पसंद करता हूं sed, क्योंकि यह स्वाभाविक रूप से कॉलम की मनमानी संख्या को संभालता है।

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv

स्पष्टीकरण:

  • -r विस्तारित रेगेक्स का चयन करता है इसलिए हम बहुत सारे बैकस्लैश से बचते हैं
  • पहला समूह कॉमा-टर्मिनेटेड स्ट्रिंग्स का $ N दोहराव है, दूसरे शब्दों में अंतिम कॉमा के साथ हम जिस कॉलम को स्थानांतरित करना चाहते हैं, उससे पहले कॉलम
  • दूसरा समूह $ एन-वें रिपीट है, हम इसके बारे में भूल जाते हैं
  • तीसरा समूह वह कॉलम है जिसे हम अंतिम कॉमा के बिना स्थानांतरित करना चाहते हैं
  • चौथा समूह उन सभी स्तंभों से बना है जिन्हें हम आगे बढ़ना चाहते हैं, इससे पहले कोई अल्पविराम नहीं था
  • हम पहले समूह, अंतिम समूह और हमारे द्वारा निकाले गए कॉलम की जगह, आवश्यकतानुसार अल्पविराम सम्मिलित करते हैं।

बेशक यह उन फ़ाइलों के साथ काम नहीं करेगा जो उद्धरणों में अल्पविराम छिपाते हैं (या इससे भी बदतर हैं, उनसे बचते हैं), लेकिन awk कुछ गंभीर कलाबाजी के बिना या तो संभाल नहीं करेगा। आपको लगता है कि समस्या है, तो आप के साथ बेहतर होगा perlमॉड्यूल Text:CSVया pythonमॉड्यूल csv


2

कुछ awkवेरिएंट (आपकी फ़ाइल को वेरिएबल के अंदर मानते हुए $file)

  • यहां आप सभी कोलॉमन के लिए साइकिल कर सकते हैं, क्षेत्र विभाजक (OFS) के साथ प्रिंट कर सकते हैं, और लाइन के अंत में रिकॉर्ड टर्मिनेटर (ORS) प्रिंट कर सकते हैं।

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
  • यहाँ एक regex और gensub()फ़ंक्शन का उपयोग करने के साथ

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"

    7 वें क्षेत्र को मारना और इसे पंक्ति के अंत में प्रिंट करना।

    • $0 पूरा रिकॉर्ड है
    • $nएन वें रिकॉर्ड है
    • NF वर्तमान लाइन के फील्ड्स की संख्या है
    • OFS आउटपुट ने विभाजक दायर किया
    • ORS आउटपुट रिकॉर्ड टर्मिनेटर
    • 1trueडिफ़ॉल्ट को जगाने और प्रिंट करने के लिए कहने के लिए चाल है ( $0)।

अपडेट करें ...

मैं लगभग भूल गया, 7 वें एक के बाद सभी स्तंभों को स्थानांतरित करना संभव है ।

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"

(1) यकीनन, OFS $7इससे ज्यादा मजबूत होगा "," $7। (२) मेरा मानना ​​है कि ", " $7यह गलत है, क्योंकि सवाल यह दर्शाता है कि ओपी अल्पविराम के बाद रिक्त स्थान नहीं चाहता है। (और, यदि इनपुट डेटा में कॉमा के बाद रिक्त स्थान था, तो $7पहले से ही एक स्थान के साथ शुरू हो जाएगा, और आप एक अतिरिक्त जोड़ देंगे।)
जी-मैन कहते हैं, 'मोनिका'

@ जी-मैन यह मुख्य रूप से कुछ विचारों, कुछ वेरिएंट्स का प्रस्ताव था। धन्यवाद, मौके के लिए, मैं इस बारे में सहमत हूं OFS $7, न केवल अधिक मजबूत, बल्कि इससे भी अधिक सामान्य ( "जल्दबाजी बेकार करता है" )
हस्तूर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.