Awk के साथ पहले क्षेत्र को छोड़कर सब कुछ मुद्रण


108

मेरे पास एक फाइल है जो इस तरह दिखती है:

AE  United Arab Emirates
AG  Antigua & Barbuda
AN  Netherlands Antilles
AS  American Samoa
BA  Bosnia and Herzegovina
BF  Burkina Faso
BN  Brunei Darussalam

और मैं $ 1 और उसके बाद $ 1 को छोड़कर पहले सब कुछ छापने के आदेश को पसंद करना चाहता हूं:

United Arab Emirates AE

मैं "फ़ील्ड 1 को छोड़कर सब कुछ कैसे कर सकता हूं" चाल?


2
हाय @ कॉफ़िशर, यह अतिरिक्त स्थान के बिना लूप कोण के बिना किया जा सकता है।
जुआन डिएगो गोडोय रॉबल्स

जवाबों:


91

$1काम सौंपना लेकिन यह एक प्रमुख स्थान छोड़ देगा:awk '{first = $1; $1 = ""; print $0, first; }'

आप NFकिसी लूप में स्तंभों की संख्या और उसका उपयोग भी कर सकते हैं ।


2
पूरी तरह से आलसी के लिए; यहाँ klashxx 'कोड है
सर्ज स्ट्रोबैंडैट

1
महान। Sed के साथ अग्रणी स्थान से छुटकारा पा लिया: awk {'first = $1; $1=""; print $0'}|sed 's/^ //g'
Thyag

VIM को सामान्य मोड में 'Ctrl + V Gd' दबाने पर आसानी से हटा दिया जाता है
Santi

107

$1=""बेन जैक्सन के रूप में एक स्थान छोड़ देता है, इसलिए एक forलूप का उपयोग करें :

awk '{for (i=2; i<=NF; i++) print $i}' filename

तो अगर आपका तार "एक दो तीन" था, तो आउटपुट होगा:

दो
तीन

यदि आप एक पंक्ति में परिणाम चाहते हैं, तो आप निम्नानुसार कर सकते हैं:

awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' filename

यह आपको देगा: "दो तीन"


4
और एक अतिरिक्त स्थान
NeronLeVelu

2
उपयोग करने के लिए बेहतर: awk '{for(i=2;i<=NF;i++){ printf("%s",( (i>2) ? OFS : "" ) $i) } ; print ;}' जो: फ़ील्ड 2 से एनएफ को प्रिंट करें, आवश्यकतानुसार आउटपुट फ़ील्ड विभाजक जोड़ें (यानी, $ 2 से पहले छोड़कर)। अंतिम प्रिंट वर्तमान लाइन प्रिंटिंग को समाप्त करने के लिए एक अंतिम न्यूलाइन जोड़ता है। यदि आप FS / OFS बदलते हैं तो यह काम करेगा (यानी, यह हमेशा "स्थान" नहीं होगा)
ओलिवियर दुलैक

दूसरे ने मेरे लिए वास्तविक अच्छा काम किया। पहला वाला, इतना नहीं। सच में यकीन नहीं क्यों। इसने पूरे पाठ को पूरा किया।
आवाजें

72

विकल्प के cutसाथ कमांड का उपयोग करें --complement:

$ echo a b c | cut -f 1 -d ' '
a
$ echo a b c | cut -f 1,2 -d ' '
a b
$ echo a b c | cut -f 1 -d ' ' --complement
b c

2
जागने के लिए विशिष्ट प्रश्न का उत्तर न देते हुए, मुझे यह सबसे उपयोगी लगा क्योंकि awk डुप्लिकेट स्थान को हटा रहा था, और कट नहीं करता है।
फमस्ट्रट

19
echo a b c | cut -d' ' -f 2- एक विकल्प है
लुइस

2
अच्छा - @ समाधान मैक पर काम करता है, जो समर्थन नहीं करता है - लागू
मेटाडाडी

21

शायद सबसे संक्षिप्त तरीका:

$ awk '{$(NF+1)=$1;$1=""}sub(FS,"")' infile
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

स्पष्टीकरण:

$(NF+1)=$1: एक "नए" अंतिम क्षेत्र के जनरेटर।

$1="": मूल प्रथम फ़ील्ड को शून्य पर सेट करें

sub(FS,""): पहले दो क्रियाओं के बाद {$(NF+1)=$1;$1=""}उप का उपयोग करके पहले क्षेत्र विभाजक से छुटकारा पाएं। अंतिम प्रिंट निहित है।


13
awk '{sub($1 FS,"")}7' YourFile

पहला फ़ील्ड और विभाजक निकालें, और परिणाम प्रिंट करें ( 7यह एक शून्य शून्य मूल्य है, इसलिए $ 0 प्रिंट करना)।


सबसे बढ़िया उत्तर! Upvoted। यह सिर्फ उपयोग करने से कैसे अलग है 1? मैं इस पैटर्न के उपयोग को आश्चर्यचकित करता हूं और यह समझना चाहता हूं। धन्यवाद!
अभिजीत रस्तोगी

10
awk '{ saved = $1; $1 = ""; print substr($0, 2), saved }'

की शुरुआत में ""एक भी प्रतिलिपि छोड़ने के लिए पहला फ़ील्ड सेट करना । यह मानते हुए कि केवल एक ही वर्ण है (डिफ़ॉल्ट रूप से, यह एकल स्थान है), हम इसे निकाल सकते हैं । फिर हम बची हुई कॉपी को जोड़ देते हैं ।OFS$0OFSsubstr($0, 2)$1


6

यदि आप एक पर्ल समाधान के लिए खुले हैं ...

perl -lane 'print join " ",@F[1..$#F,0]' file

एक अंतरिक्ष के इनपुट / आउटपुट विभाजक के साथ एक सरल समाधान है, जो उत्पादन करता है:

United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

यह अगला थोड़ा अधिक जटिल है

perl -F`  ` -lane 'print join "  ",@F[1..$#F,0]' file

और मानता है कि इनपुट / आउटपुट विभाजक दो स्थान है:

United Arab Emirates  AE
Antigua & Barbuda  AG
Netherlands Antilles  AN
American Samoa  AS
Bosnia and Herzegovina  BA
Burkina Faso  BF
Brunei Darussalam  BN

इन कमांड-लाइन विकल्पों का उपयोग किया जाता है:

  • -n इनपुट फ़ाइल की प्रत्येक पंक्ति के चारों ओर लूप, स्वचालित रूप से प्रत्येक पंक्ति को प्रिंट न करें

  • -l प्रसंस्करण से पहले नए सिरे को हटाता है, और बाद में उन्हें वापस जोड़ता है

  • -aऑटोसप्लिट मोड - @F सरणी में इनपुट लाइनों को विभाजित करें। व्हॉट्सएप पर बंटवारे की चूक

  • -F ऑटोसप्लिट संशोधक, इस उदाहरण में '' (दो स्थान) पर विभाजित होता है

  • -e निम्नलिखित पर्ल कोड निष्पादित करें

@Fप्रत्येक पंक्ति में शब्दों की सरणी है, 0
$#Fसे शुरू होने वाले अनुक्रमित में शब्दों की संख्या है। @F
@F[1..$#F]तत्व
@F[1..$#F,0]का एक सरणी टुकड़ा है अंतिम तत्व के माध्यम से 1 तत्व का सरणी टुकड़ा है अंतिम तत्व के साथ तत्व 1 है


1
मैं इसे चलाता हूं और अंत में एक अतिरिक्त संख्या थी इसलिए मैंने इस संस्करण का उपयोग किया है: perl -lane 'shift @F; प्रिंट जॉइन "", @ एफ '
हंस पू

2

गॉव में क्षेत्र विभाजक (कम से कम) एक स्ट्रिंग के साथ-साथ एक चरित्र भी हो सकता है (यह एक रेगेक्स भी हो सकता है)। यदि आपका डेटा सुसंगत है, तो यह काम करेगा:

awk -F "  " '{print $2,$1}' inputfile

दोहरे उद्धरण चिह्नों के बीच दो रिक्त स्थान हैं।


हाथ में स्थिति के लिए सबसे अच्छा जवाब है, लेकिन, तकनीकी रूप से, यह इस सवाल का जवाब नहीं देता है कि सब कुछ कैसे प्रिंट किया जाए लेकिन पहला क्षेत्र।
डेन मोल्डिंग

@DanMoulding: जब तक फ़ाइल देश कोड को अलग करने के लिए दो स्थानों के उपयोग में सुसंगत है और एक साथ दो स्थानों की कोई अन्य घटना नहीं होती है, मेरा जवाब प्रश्न को संबोधित करता है
अगली सूचना तक रोक दिया गया।

2
इस सवाल पर उतरने वाले लोग यहां पहुंचते हैं क्योंकि वे जानना चाहते हैं कि सब कुछ कैसे प्रिंट किया जाए लेकिन पहला क्षेत्र (प्रश्न शीर्षक देखें)। इसी तरह मैं यहां उतरा। आपके उत्तर से पता चलता है कि दूसरे क्षेत्र के बाद पहले क्षेत्र को कैसे प्रिंट किया जाए। जबकि यह संभवतः ओपी की विशेष स्थिति का सबसे अच्छा समाधान है, लेकिन यह सामान्य समस्या को हल नहीं करता है कि सब कुछ कैसे प्रिंट किया जाए लेकिन पहला क्षेत्र।
दान मोल्डिंग


2

आइए सभी रिकॉर्डों को अगले एक पर ले जाएं और अंतिम को पहले के रूप में सेट करें:

$ awk '{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' file
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

व्याख्या

  • a=$1 एक अस्थायी चर में पहला मान सहेजें।
  • for (i=2; i<=NF; i++) $(i-1)=$i N (N-1) वें फ़ील्ड में Nth फ़ील्ड मान सहेजें।
  • $NF=a$1अंतिम फ़ील्ड में पहला मान ( ) सहेजें ।
  • {}1awkडिफ़ॉल्ट क्रिया करने के लिए सही स्थिति {print $0}:।

इस तरह, यदि आप एक और क्षेत्र विभाजक होने के लिए, परिणाम भी अच्छा है:

$ cat c
AE-United-Arab-Emirates
AG-Antigua-&-Barbuda
AN-Netherlands-Antilles
AS-American-Samoa
BA-Bosnia-and-Herzegovina
BF-Burkina-Faso
BN-Brunei-Darussalam

$ awk 'BEGIN{OFS=FS="-"}{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' c
United-Arab-Emirates-AE
Antigua-&-Barbuda-AG
Netherlands-Antilles-AN
American-Samoa-AS
Bosnia-and-Herzegovina-BA
Burkina-Faso-BF
Brunei-Darussalam-BN

1

इस पर एक पहला छुरा आपके विशेष मामले के लिए काम करने लगता है।

awk '{ f = $1; i = $NF; while (i <= 0); gsub(/^[A-Z][A-Z][ ][ ]/,""); print $i, f; }'

1

विकल्प 1

एक समाधान है जो awk के कुछ संस्करणों के साथ काम करता है:

awk '{ $(NF+1)=$1;$1="";$0=$0;} NF=NF ' infile.txt

स्पष्टीकरण:

       $(NF+1)=$1                          # add a new field equal to field 1.
                  $1=""                    # erase the contents of field 1.
                        $0=$0;} NF=NF      # force a re-calc of fields.
                                           # and use NF to promote a print.

परिणाम:

United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

हालाँकि यह पुराने संस्करणों के साथ विफल हो सकता है।


विकल्प 2

awk '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt

अर्थात्:

awk '{                                      # call awk.
       $(NF+1)=$1;                          # Add one trailing field.
                  $1="";                    # Erase first field.
                        sub(OFS,"");        # remove leading OFS.
                                    }1'     # print the line.

ध्यान दें कि जिसे मिटाने की जरूरत है वह ओएफएस नहीं बल्कि ओएफएस है। जब फ़ील्ड $ 1 असाइन किया जाता है, तो रेखा फिर से परिकलित हो जाती है। यह FS के सभी रन को एक OFS में बदल देता है।


लेकिन यह विकल्प अभी भी कई सीमांकक के साथ विफल रहता है, जैसा कि ओएफएस को बदलकर स्पष्ट रूप से दिखाया गया है:

awk -v OFS=';' '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt

वह लाइन आउटपुट करेगी:

United;Arab;Emirates;AE
Antigua;&;Barbuda;AG
Netherlands;Antilles;AN
American;Samoa;AS
Bosnia;and;Herzegovina;BA
Burkina;Faso;BF
Brunei;Darussalam;BN

यह पता चलता है कि एफएस के रन को ओएफएस में बदल दिया जा रहा है।
इससे बचने का एकमात्र तरीका क्षेत्र फिर से गणना से बचना है।
एक फ़ंक्शन जो फिर से कैल्क से बच सकता है वह उप है।
पहले क्षेत्र पर कब्जा किया जा सकता है, फिर उप के साथ $ 0 से हटा दिया गया, और फिर दोनों ने फिर से मुद्रित किया।

विकल्प 3

awk '{ a=$1;sub("[^"FS"]+["FS"]+",""); print $0, a;}' infile.txt
       a=$1                                   # capture first field.
       sub( "                                 # replace: 
             [^"FS"]+                         # A run of non-FS
                     ["FS"]+                  # followed by a run of FS.
                            " , ""            # for nothing.
                                  )           # Default to $0 (the whole line.
       print $0, a                   # Print in reverse order, with OFS.


United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

यहां तक ​​कि अगर हम एफएस, ओएफएस और / या अधिक सीमांकक को बदलते हैं, तो यह काम करता है।
यदि इनपुट फ़ाइल को बदल दिया जाता है:

AE..United....Arab....Emirates
AG..Antigua....&...Barbuda
AN..Netherlands...Antilles
AS..American...Samoa
BA..Bosnia...and...Herzegovina
BF..Burkina...Faso
BN..Brunei...Darussalam

और कमांड में परिवर्तन होता है:

awk -vFS='.' -vOFS=';' '{a=$1;sub("[^"FS"]+["FS"]+",""); print $0,a;}' infile.txt

उत्पादन होगा (अभी भी सीमांकक संरक्षण):

United....Arab....Emirates;AE
Antigua....&...Barbuda;AG
Netherlands...Antilles;AN
American...Samoa;AS
Bosnia...and...Herzegovina;BA
Burkina...Faso;BF
Brunei...Darussalam;BN

कमांड को कई क्षेत्रों में विस्तारित किया जा सकता है, लेकिन केवल आधुनिक awks और --re-interval विकल्प के साथ सक्रिय है। मूल फ़ाइल पर यह आदेश:

awk -vn=2 '{a=$1;b=$2;sub("([^"FS"]+["FS"]+){"n"}","");print $0,a,b;}' infile.txt

इसका उत्पादन करेगा:

Arab Emirates AE United
& Barbuda AG Antigua
Antilles AN Netherlands
Samoa AS American
and Herzegovina BA Bosnia
Faso BF Burkina
Darussalam BN Brunei


0

वहाँ एक sed विकल्प भी है ...

 sed 's/\([^ ]*\)  \(.*\)/\2 \1/' inputfile.txt

व्याख्या की...

Swap
\([^ ]*\) = Match anything until we reach a space, store in $1
\(.*\)    = Match everything else, store in $2
With
\2        = Retrieve $2
\1        = Retrieve $1

अधिक अच्छी तरह से समझाया ...

s    = Swap
/    = Beginning of source pattern
\(   = start storing this value
[^ ] = text not matching the space character
*    = 0 or more of the previous pattern
\)   = stop storing this value
\(   = start storing this value
.    = any character
*    = 0 or more of the previous pattern
\)   = stop storing this value
/    = End of source pattern, beginning of replacement
\2   = Retrieve the 2nd stored value
\1   = Retrieve the 1st stored value
/    = end of replacement

0

फिर भी एक और तरीका ...

... यह एफएस के साथ एनएफ 2 क्षेत्रों के साथ जुड़ता है और इनपुट के प्रति लाइन एक लाइन आउटपुट करता है

awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'

मैं यह देखने के लिए git के साथ इसका उपयोग करता हूं कि मेरे कार्यशील dir में कौन सी फाइलें संशोधित की गई हैं:

git diff| \
    grep '\-\-git'| \
    awk '{print$NF}'| \
    awk -F"/" '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'

-3

कैट कमांड का उपयोग करके एक और आसान और आसान तरीका

cat filename | awk '{print $2,$3,$4,$5,$6,$1}' > newfilename

मैंने यह नकार दिया क्योंकि यह एक गतिशील दृष्टिकोण नहीं है। इसके साथ आपको तर्कों की संख्या जानने और अपने डेटा को सुसंगत मानने की आवश्यकता है। डेटा लगभग कभी भी सुसंगत नहीं होता है और आपके दृष्टिकोण को अधिकांश समय इसे ध्यान में रखना चाहिए।
xh3b4sd
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.