कट का उपयोग करके कॉलम को पुनर्व्यवस्थित करें


135

मैं निम्नलिखित प्रारूप में एक फाइल कर रहा हूं

कॉलम 1 कॉलम 2
str1 1
तार २
str3 3

मैं चाहता हूं कि स्तंभों को फिर से व्यवस्थित किया जाए। मैंने कमांड के नीचे कोशिश की

cut -f2,1 file.txt

आदेश स्तंभों को पुन: व्यवस्थित नहीं करता है। किसी भी विचार क्यों काम नहीं कर रहा है?

धन्यवाद।

जवाबों:


148

के लिए cut(1)आदमी पेज:

एक का उपयोग करें, और केवल -b, -c या -f में से एक का उपयोग करें। प्रत्येक LIST एक सीमा से बना होता है, या कई श्रेणी अल्पविराम द्वारा अलग होती हैं। चयनित इनपुट उसी क्रम में लिखा जाता है जिसे वह पढ़ा जाता है, और ठीक एक बार लिखा जाता है।

यह पहले फ़ील्ड 1 पर पहुँचता है, इसलिए यह प्रिंट होता है, इसके बाद फ़ील्ड 2 आता है।

awkइसके बजाय उपयोग करें :

awk '{ print $2 " " $1}' file.txt

12
यह बहुत बुरा cutहै यह सहज ज्ञान युक्त री-ऑर्डरिंग आदेश का समर्थन नहीं करता है। वैसे भी, एक और टिप: आप उपयोग कर सकते awkहै -FSऔर -OFSविकल्प के लिए उपयोग कस्टम इनपुट और आउटपुट क्षेत्र विभाजक (जैसे -dऔर --output-delimiterके लिए cut)।
मलाना

12
क्षमा करें, FSएक विकल्प है, OFSएक चर है। जैसेawk -v OFS=";" -F"\t" '{print $2,$1}'
malana

2
गिट बैश के विंडोज उपयोगकर्ताओं पर ध्यान दें: यदि आपके पास ऊपर दिए गए कमांड से अजीब आउटपुट हैं, तो एक-दूसरे को ओवरराइड करते हुए कॉलम की तरह लग रहे हैं, तो गाड़ी का रिटर्न दोष देना है। CRLF से LF में अपनी फाइल में EOL बदलें।
jakub.g 12

1
वैकल्पिक रूप से यदि आप इनपुट फ़ाइल को बदलना नहीं चाहते हैं, तो आप पाइप करने से | sed 's/\r//' | पहले इसे पाइप सेawk
jakub.g

2
यह एक बहुत ही सरल है, लेकिन कुछ के लिए उपयोगी हो सकता है, बस टैब द्वारा पुनawk '{print $4 "\t" $2 "\t" $6 "\t" $7}' file
व्यवस्थित करने के

64

आप भी जोड़ सकते हैं cutऔर paste:

paste <(cut -f2 file.txt) <(cut -f1 file.txt)

टिप्पणियों के माध्यम से: यह संभव है कि मार से बचने के लिए और कट की एक आवृत्ति को हटा दें:

paste file.txt file.txt | cut -f2,3

3
सुनिश्चित नहीं है कि यह "चतुराई" के रूप में योग्य है, लेकिन: f = file.txt पेस्ट <(cut -f2 $ f) <(cut -f1 $ f)। इसके अलावा, मैं ध्यान देता हूं कि यह विधि सबसे आसान है जब आपके पास बहुत सारे कॉलम हैं और उनमें से बड़े ब्लॉकों को घूमना चाहते हैं।
माइकल रस्च

एक ही कॉलम में चर लंबाई की कोशिकाओं के साथ काम नहीं करता है
kremer

2
@kraymer आपका क्या मतलब है? cutजब तक आपके पास एक अद्वितीय स्तंभ विभाजक है, तब तक चर-लंबाई वाले स्तंभों के लिए ठीक काम करता है।
तिकड़ी

1
निरर्थक फ़ाइल को समाप्त करने के लिए आप शायद टी का उपयोग कर सकते हैं:
JJW5432

2
यह से बचने के लिए संभव है bashवाद और का एक उदाहरण को दूर cut: करके paste file.txt file.txt | cut -f2,3
एजीसी

7

सिर्फ शेल का उपयोग करके,

while read -r col1 col2
do
  echo $col2 $col1
done <"file"

यह बहुत बार अक्षम है। आमतौर पर, आप पाएंगे कि संबंधित Awk स्क्रिप्ट बहुत तेज है, उदाहरण के लिए। आपको मूल्यों को उद्धृत करने के लिए भी सावधान रहना चाहिए - "$col2"और "$col1"डेटा में शेल मेटाचैकर या अन्य शेंनिगन हो सकते हैं।
ट्रिपलए

7

आप उसके लिए पर्ल का उपयोग कर सकते हैं:

perl -ane 'print "$F[1] $F[0]\n"' < file.txt
  • -इस विकल्प का अर्थ है कि इसके बाद कमांड निष्पादित करें
  • -n का अर्थ है लाइन से लाइन पढ़ें (फ़ाइल खोलें, इस स्थिति में STDOUT और लूप ओवर लाइन)
  • -a का अर्थ है ऐसी पंक्तियों को @F ("F" - जैसे फ़ील्ड) कहा जाता है। पर्ल इंडेक्स वैक्टर 0 से शुरू होता है जो कट के विपरीत होता है जो फार्म 1 को शुरू करता है।
  • आप डिफ़ॉल्ट व्हाट्सएप के बजाय फाइल को पढ़ते समय क्षेत्र विभाजक के रूप में पैटर्न का उपयोग करने के लिए -F पैटर्न (-F और पैटर्न के बीच कोई स्थान नहीं) के साथ जोड़ सकते हैं

पर्ल को चलाने का लाभ यह है कि (यदि आप पर्ल को जानते हैं) तो आप रीयररेंजिंग कॉलम की तुलना में एफ पर बहुत अधिक गणना कर सकते हैं।


perlrun (1) का दावा है-का तात्पर्य सेट -n है लेकिन अगर मैं बिना n-सेट के चलता हूं, तो यह लूप नहीं लगता है। अजीब।
ट्रेंटन

क्या संस्करण? मेरे लिए perl -ae printकाम करता हैcat
pwes

5

का उपयोग कर join:

join -t $'\t' -o 1.2,1.1 file.txt file.txt

टिप्पणियाँ:

  • -t $'\t'में जीएनयू join अधिक सहज ज्ञान युक्त -t '\t' बिना$ विफल रहता है, ( coreutils v8.28 और पहले?); यह शायद एक बग है कि वर्कअराउंड की तरह $आवश्यक होना चाहिए। देखें: यूनिक्स विभाजक चार में शामिल होने के

  • joinदो फ़ाइलनामों की आवश्यकता है, भले ही वहाँ केवल एक फ़ाइल पर काम किया जा रहा हो। joinवांछित क्रिया करने में दो बार समान नाम का उपयोग करना ।

  • कम संसाधनों वाली प्रणालियों के लिए joinअन्य उत्तरों में प्रयुक्त कुछ उपकरणों की तुलना में एक छोटा पदचिह्न प्रदान करता है:

    wc -c $(realpath `which cut join sed awk perl`) | head -n -1
      43224 /usr/bin/cut
      47320 /usr/bin/join
     109840 /bin/sed
     658072 /usr/bin/gawk
    2093624 /usr/bin/perl

3

बस कुछ इसी तरह काम कर रहा हूं, मैं एक विशेषज्ञ नहीं हूं, लेकिन मुझे लगा कि मैं उन कमांडों को साझा करूंगा जिनका मैंने उपयोग किया है। मेरे पास एक मल्टी कॉलम सीएसवी था जिसमें मुझे केवल 4 कॉलमों की आवश्यकता थी और फिर मुझे उन्हें पुनः व्यवस्थित करने की आवश्यकता थी।

मेरी फ़ाइल 'पाइप थी।' सीमांकित लेकिन वह अदला-बदली की जा सकती है।

LC_ALL=C cut -d$'|' -f1,2,3,8,10 ./file/location.txt | sed -E "s/(.*)\|(.*)\|(.*)\|(.*)\|(.*)/\3\|\5\|\1\|\2\|\4/" > ./newcsv.csv

माना जाता है कि यह वास्तव में खुरदरा और तैयार है लेकिन इसे सूट किया जा सकता है!


यह प्रश्न का उत्तर नहीं देता है। स्टैक ओवरफ्लो की भावना में आप पोस्ट करने से पहले एक समस्या का जवाब देने के लिए समय दें।
बिल गाले

0

Sed का उपयोग करना

स्तंभ सामग्री को कैप्चर करने और पुन: व्यवस्थित करने के लिए मूल नियमित अभिव्यक्ति के नेस्टेड सबएक्सप्रेस के साथ sed का उपयोग करें। जब इस मामले में पुन: स्तंभों की सीमित संख्या में कटौती होती है, तो यह दृष्टिकोण सबसे उपयुक्त होता है।

मूल विचार खोज पैटर्न के दिलचस्प अंशों को घेरना है \(और \), जिन्हें प्रतिस्थापन पैटर्न में वापस खेला जा सकता है, \#जहां #खोज पैटर्न में उपसंचाई की अनुक्रमिक स्थिति का प्रतिनिधित्व करता है।

उदाहरण के लिए:

$ echo "foo bar" | sed "s/\(foo\) \(bar\)/\2 \1/"

पैदावार:

bar foo

सब-डेफ़िसिएशन के बाहर का पाठ स्कैन किया गया है लेकिन प्रतिस्थापन स्ट्रिंग में प्लेबैक के लिए इसे बरकरार नहीं रखा गया है।

यद्यपि प्रश्न में निश्चित चौड़ाई के स्तंभों पर चर्चा नहीं की गई है, हम यहां चर्चा करेंगे क्योंकि यह किसी भी समाधान के योग्य उपाय है। सरलता के लिए मान लेते हैं कि फ़ाइल स्पेस सीमांकित है, हालांकि समाधान को अन्य सीमांकक के लिए बढ़ाया जा सकता है।

Collapsing Spaces

सरलतम उपयोग को स्पष्ट करने के लिए, मान लेते हैं कि कई स्थानों को एकल स्थानों में ढहाया जा सकता है, और दूसरे स्तंभ मानों को ईओएल के साथ समाप्त किया जाता है (और अंतरिक्ष में गद्देदार नहीं)।

फ़ाइल:

bash-3.2$ cat f
Column1    Column2
str1       1
str2       2
str3       3
bash-3.2$ od -a f
0000000    C   o   l   u   m   n   1  sp  sp  sp  sp   C   o   l   u   m
0000020    n   2  nl   s   t   r   1  sp  sp  sp  sp  sp  sp  sp   1  nl
0000040    s   t   r   2  sp  sp  sp  sp  sp  sp  sp   2  nl   s   t   r
0000060    3  sp  sp  sp  sp  sp  sp  sp   3  nl 
0000072

रूपांतरण करें:

bash-3.2$ sed "s/\([^ ]*\)[ ]*\([^ ]*\)[ ]*/\2 \1/" f
Column2 Column1
1 str1
2 str2
3 str3
bash-3.2$ sed "s/\([^ ]*\)[ ]*\([^ ]*\)[ ]*/\2 \1/" f | od -a
0000000    C   o   l   u   m   n   2  sp   C   o   l   u   m   n   1  nl
0000020    1  sp   s   t   r   1  nl   2  sp   s   t   r   2  nl   3  sp
0000040    s   t   r   3  nl
0000045

कॉलम चौड़ाई का संरक्षण

आइए अब किसी फ़ाइल को विधि को निरंतर चौड़ाई वाले स्तंभों के साथ बढ़ाते हैं, जबकि स्तंभों को अलग-अलग चौड़ाई वाले होते हैं।

फ़ाइल:

bash-3.2$ cat f2
Column1    Column2
str1       1
str2       2
str3       3
bash-3.2$ od -a f2
0000000    C   o   l   u   m   n   1  sp  sp  sp  sp   C   o   l   u   m
0000020    n   2  nl   s   t   r   1  sp  sp  sp  sp  sp  sp  sp   1  sp
0000040   sp  sp  sp  sp  sp  nl   s   t   r   2  sp  sp  sp  sp  sp  sp
0000060   sp   2  sp  sp  sp  sp  sp  sp  nl   s   t   r   3  sp  sp  sp
0000100   sp  sp  sp  sp   3  sp  sp  sp  sp  sp  sp  nl
0000114

रूपांतरण करें:

bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f2
Column2 Column1
1       str1      
2       str2      
3       str3      
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f2 | od -a
0000000    C   o   l   u   m   n   2  sp   C   o   l   u   m   n   1  sp
0000020   sp  sp  nl   1  sp  sp  sp  sp  sp  sp  sp   s   t   r   1  sp
0000040   sp  sp  sp  sp  sp  nl   2  sp  sp  sp  sp  sp  sp  sp   s   t
0000060    r   2  sp  sp  sp  sp  sp  sp  nl   3  sp  sp  sp  sp  sp  sp
0000100   sp   s   t   r   3  sp  sp  sp  sp  sp  sp  nl 
0000114

अंत में, हालांकि प्रश्न के उदाहरण में असमान लंबाई के तार नहीं हैं, यह सेड अभिव्यक्ति इस मामले का समर्थन करती है।

फ़ाइल:

bash-3.2$ cat f3
Column1    Column2
str1       1      
string2    2      
str3       3      

रूपांतरण करें:

bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f3
Column2 Column1   
1       str1      
2       string2   
3       str3    
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f3 | od -a
0000000    C   o   l   u   m   n   2  sp   C   o   l   u   m   n   1  sp
0000020   sp  sp  nl   1  sp  sp  sp  sp  sp  sp  sp   s   t   r   1  sp
0000040   sp  sp  sp  sp  sp  nl   2  sp  sp  sp  sp  sp  sp  sp   s   t
0000060    r   i   n   g   2  sp  sp  sp  nl   3  sp  sp  sp  sp  sp  sp
0000100   sp   s   t   r   3  sp  sp  sp  sp  sp  sp  nl 
0000114

खोल के नीचे स्तंभ के अन्य तरीकों की तुलना

  • एक फ़ाइल हेरफेर उपकरण के लिए आश्चर्यजनक रूप से, awk एक क्षेत्र से रिकॉर्ड के अंत तक काटने के लिए अच्छी तरह से अनुकूल नहीं है। Sed में यह नियमित अभिव्यक्तियों का उपयोग करके पूरा किया जा सकता है, उदाहरण के लिए स्तंभ से मेल खाने के लिए अभिव्यक्ति \(xxx.*$\)कहाँ xxxहै।

  • शेल स्क्रिप्ट्स को लागू करते समय पेस्ट और कट सबस्क्रिप्शन का उपयोग करना मुश्किल हो जाता है। कमांड से काम करने वाला कोड शेल स्क्रिप्ट के अंदर लाए जाने पर पार्स करने में विफल रहता है। कम से कम यह मेरा अनुभव था (जो मुझे इस दृष्टिकोण तक ले गया)।


0

@Met से उत्तर पर विस्तार करते हुए, पर्ल का उपयोग करते हुए भी:
यदि इनपुट और आउटपुट TAB- सीमांकित हैं:

perl -F'\t' -lane 'print join "\t", @F[1, 0]' in_file

यदि इनपुट और आउटपुट व्हाट्सएप-सीमांकित हैं:

perl -lane 'print join " ", @F[1, 0]' in_file

यहाँ,
-eपर्ल को एक अलग स्क्रिप्ट फ़ाइल के बजाय कोड इनलाइन देखने के लिए कहता है ,
-nएक बार में इनपुट 1 लाइन पढ़ता है , लाइन पढ़ने के बाद
-lइनपुट रिकॉर्ड विभाजक ( \n* NIX) को हटाता है (समान chomp), और आउटपुट जोड़ें रिकॉर्ड विभाजक ( \nप्रत्येक के लिए * NIX पर) print,
-aसरणी में खाली स्थान के पर इनपुट लाइन विभाजन @F,
-F'\t'संयोजन में साथ -aविभाजन टैब पर इनपुट लाइन, खाली स्थान के के बजाय सरणी में@F

@F[1, 0]@Fइस क्रम में सरणी के 2 और 1 तत्वों से बना सरणी है । याद रखें कि पर्ल में सरणियाँ शून्य-अनुक्रमित हैं, जबकि फ़ील्ड cut1-अनुक्रमित हैं। तो फ़ील्ड्स @F[0, 1]उसी फ़ील्ड के समान हैं, जिसमें वाले फ़ील्ड हैंcut -f1,2

ध्यान दें कि इस तरह के संकेतन ऊपर पोस्ट किए गए कुछ अन्य उत्तरों की तुलना में इनपुट के अधिक लचीले हेरफेर को सक्षम बनाता है (जो एक साधारण कार्य के लिए ठीक हैं)। उदाहरण के लिए:

# reverses the order of fields:
perl -F'\t' -lane 'print join "\t", reverse @F' in_file

# prints last and first fields only:
perl -F'\t' -lane 'print join "\t", @F[-1, 0]' in_file
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.