क्या UNIX सॉर्ट में हेडर लाइनों को अनदेखा करने का कोई तरीका है?


102

मेरे पास एक निश्चित-चौड़ाई वाली फ़ील्ड फ़ाइल है जिसे मैं UNIX (साइगविन, मेरे मामले में) सॉर्ट यूटिलिटी का उपयोग करके सॉर्ट करने की कोशिश कर रहा हूं।

समस्या यह है कि फ़ाइल के शीर्ष पर एक दो-पंक्ति हैडर है जो फ़ाइल के निचले भाग में सॉर्ट किया जा रहा है (जैसा कि प्रत्येक हेडर लाइन एक कोलोन के साथ शुरू होता है)।

क्या कोई ऐसा तरीका है जो या तो "पहले दो पंक्तियों को अनसोल्ड में पास करें" या एक ऑर्डर निर्दिष्ट करने के लिए है जो बृहदान्त्र लाइनों को ऊपर की ओर छाँटता है - शेष पंक्तियाँ हमेशा 6-अंकीय न्यूमेरिक से शुरू होती हैं (जो वास्तव में कुंजी है मदद करता है) अगर मैं पर छँटाई कर रहा हूँ।

उदाहरण:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
500123TSTMY_RADAR00
222334NOTALINEOUT01
477821USASHUTTLES21
325611LVEANOTHERS00

के लिए सॉर्ट करना चाहिए:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
222334NOTALINEOUT01
325611LVEANOTHERS00
477821USASHUTTLES21
500123TSTMY_RADAR00

रिकॉर्ड के लिए: अब तक मैं जिस कमांड लाइन का उपयोग कर रहा हूं, वह है "सॉर्ट -t \\ -k1.1,1.6 <file>" [डेटा में स्पेस हो सकता है, लेकिन बैकस्लैश कभी नहीं होगा]
Rob Gilliam

जवाबों:


125
(head -n 2 <file> && tail -n +3 <file> | sort) > newfile

कोष्ठक एक उपधारा बनाते हैं, स्टडआउट को लपेटते हैं ताकि आप इसे पाइप कर सकें या इसे पुनर्निर्देशित कर सकें जैसे कि यह एक ही कमांड से आया था।


धन्यवाद; मैं इस जवाब को स्वीकार कर रहा हूं क्योंकि यह सबसे पूर्ण और संक्षिप्त लगता है (और मैं समझता हूं कि यह क्या कर रहा है!) - यह "हेड-एन 2" होना चाहिए, हालांकि :-)
रोब गिल्मिन

1
धन्यवाद, 'सिर' हिस्सा तय किया।
BobS

4
क्या इस संस्करण को पाइप-इन डेटा पर काम करने का कोई तरीका है? मैंने कोशिश की tee >(head -n $header_size) | tail -n +$header_size | sort, लेकिन tail|sortपाइप के बाद सिर चलने लगता है , इसलिए हेडर अंत में मुद्रित होता है। यह नियतात्मक है या जातिगत स्थिति है?
डेमियन पोललेट

आप शायद किसी चीज को एक साथ जोड़ सकते हैं, जहां आप catएक अस्थायी फ़ाइल पर स्टड को पुनर्निर्देशित करने के लिए उपयोग करते हैं, फिर उस नई फ़ाइल पर उपरोक्त कमांड चलाएं, लेकिन यह बदसूरत पर्याप्त रूप से प्राप्त करना शुरू कर रहा है जो संभवतः दिए गए awk- आधारित समाधानों में से एक का उपयोग करना बेहतर है अन्य प्रतिक्रियाएँ।
बॉब्स

@DamienPollet: डेव का जवाब देखें ।
जोनाथन लेफ़लर

63

यदि आप का उपयोग करने में कोई आपत्ति नहीं है awk, तो आप इसका लाभ उठा सकते हैंawk अंतर्निहित पाइप क्षमताओं का

जैसे।

extract_data | awk 'NR<3{print $0;next}{print $0| "sort -r"}' 

यह पहली दो पंक्तियों को शब्दशः प्रिंट करता है और बाकी को पाइप के जरिए sort

ध्यान दें कि यह एक विशिष्ट इनपुट इनपुट के कुछ हिस्सों को चुनने में सक्षम होने का बहुत विशिष्ट लाभ है। सुझाई गई अन्य सभी विधियाँ केवल सादा फ़ाइलों को छाँटेंगी जिन्हें कई बार पढ़ा जा सकता है। यह किसी भी चीज पर काम करता है।


2
बहुत अच्छा है, और यह न केवल फाइलों के साथ, मनमाने पाइप के साथ काम करता है!
लापो

4
सुंदर, जाग कभी भी मुझे आश्चर्यचकित नहीं करता है। इसके अलावा, आप की जरूरत नहीं है $0, printपर्याप्त है।
नाचोकाब

1
@SamWatkins के फ्रीसाइक का जवाब कम बदसूरत है।
डर।

क्या -r विकल्प सॉर्ट करने के लिए कर रहा है? क्या यह रिवर्स सॉर्ट माना जाता है?
gvrocha

32

यहां एक संस्करण है जो पाइप किए गए डेटा पर काम करता है:

(read -r; printf "%s\n" "$REPLY"; sort)

यदि आपके हेडर में कई लाइनें हैं:

(for i in $(seq $HEADER_ROWS); do read -r; printf "%s\n" "$REPLY"; done; sort)

यह समाधान यहाँ से है


9
अच्छा। सिंगल हेडर केस के लिए मैं extract_data | (read h; echo "$h"; sort) इसे याद रखने के लिए बहुत कम उपयोग करता हूं । आपके उदाहरण में अधिक धार वाले मामले शामिल हैं। :) यह सबसे अच्छा जवाब है। पाइप पर काम करता है। जाग नहीं रहा।
डर।

1
ठीक है, मैंने यह स्ट्रैप किया है और ऐसा लगता है कि बैश इस काम को करने के लिए विशेष लंबाई में जाता है। सामान्य तौर पर, यदि आपने इसे C या किसी अन्य भाषा में कोडित किया है तो यह काम नहीं करेगा क्योंकि stdio सिर्फ पहली हेडर लाइन से अधिक पढ़ेगा। यदि आप इसे एक खोज योग्य फ़ाइल पर चलाते हैं, तो बैश एक बड़ा हिस्सा पढ़ता है (मेरे परीक्षण में 128 बाइट्स), फिर पहली पंक्ति के अंत के बाद वापस लेसे। यदि आप इसे एक पाइप पर चलाते हैं, तो bash एक बार में एक चार बार पढ़ता है जब तक कि यह पंक्ति के अंत तक नहीं जाता है।
सैम वाटकिंस

अच्छा! अगर आप सिर्फ हेडर खाना चाहते हैं, तो यह याद रखना और भी आसान है:extract_data | (read; sort)
जेसन सुआरेज़

यह एक लगभग सही है, लेकिन आपको अग्रणी और अनुगामी रिक्त स्थान रखने के लिए "पढ़ने" के बजाय "IFS = पढ़ें" का उपयोग करने की आवश्यकता है।
स्टेनिस्लाव जर्मन-इवतुशेंको

6
यह मेरी राय में स्वीकृत उत्तर होना चाहिए। सरल, संक्षिप्त और अधिक लचीला है कि यह पाइप किए गए डेटा पर भी काम करता है।
पॉल I

12

साधारण मामलों में, sedकाम को सुरुचिपूर्ण ढंग से कर सकते हैं:

    your_script | (sed -u 1q; sort)

या समकक्ष,

    cat your_data | (sed -u 1q; sort)

कुंजी में है 1q- प्रिंट पहली पंक्ति (हेडर) और छोड़ दिया (इनपुट के बाकी को छोड़कर sort)।

दिए गए उदाहरण के लिए, 2q ट्रिक करेंगे।

-uस्विच (unbuffered) उन लोगों के लिए आवश्यक है sedरों (विशेष रूप से, जीएनयू की) है कि अन्यथा, मात्रा में इनपुट पढ़ता था जिससे डेटा लेने वाली है कि आप के माध्यम से जाना चाहते हैं, sortबजाय।


1
हाय, @Andrea; स्टैक ओवरफ्लो में आपका स्वागत है। मुझे डर है कि आपका जवाब काम नहीं करता है, कम से कम नहीं जब मैं इसे विंडोज पर गिट बैश में परीक्षण कर रहा हूं (मैं Cygwin से आगे बढ़ा हूं, शेल मैं 6 साल पहले एक अलग नौकरी का उपयोग कर रहा था)। सेड कमांड, स्टड को बंद करने के लिए कोई डेटा नहीं छोड़ता है, स्टड से सभी डेटा को खींचता है। कमांड बदलने का प्रयास करें cat_data | (sed 1q; wc -l) यह देखने के लिए कि मेरा क्या मतलब है।
रॉब गिलियम

1
यदि आप दूसरी बार इनपुट को कमांड कमांड में पास करते हैं तो यह काम कर सकता है, जैसे: cat SortMe.csv | (sed 1q SortMe.csv; सॉर्ट -t, -k3 -rn)> Sorted.csv
हैरी क्रैमर

8

आप का उपयोग कर सकते हैं tail -n +3 <file> | sort ...(पूंछ तीसरी पंक्ति से फ़ाइल सामग्री का उत्पादन करेगी)।


4
head -2 <your_file> && nawk 'NR>2' <your_file> | sort

उदाहरण:

> cat temp
10
8
1
2
3
4
5
> head -2 temp && nawk 'NR>2' temp | sort -r
10
8
5
4
3
2
1

3

यह केवल कोड की 2 लाइनें लेता है ...

head -1 test.txt > a.tmp; 
tail -n+2 test.txt | sort -n >> a.tmp;

एक संख्यात्मक डेटा के लिए, -n की आवश्यकता है। अल्फा सॉर्ट के लिए, -n की आवश्यकता नहीं है।

उदाहरण फ़ाइल:
$ cat test.txt

हेडर
8
5
100
1
-1

परिणाम:
$ cat a.tmp

हैडर
-1
1
5
8
100


1
क्या यह मूल रूप से स्वीकृत उत्तर के समान उत्तर नहीं है? (बॉब के दृष्टिकोण को छोड़कर परिणाम को स्टडआउट पर रखा गया है, जिससे आपको फ़ाइल को लिखे जाने से पहले अन्य फिल्टर के माध्यम से परिणाम भेजने की अनुमति मिलती है, यदि आवश्यक हो)
रोब गिलियम

1

तो यहाँ एक बश फ़ंक्शन है जहाँ तर्क बिल्कुल सॉर्ट की तरह हैं। फाइल और पाइप को सपोर्ट करना।

function skip_header_sort() {
    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
        local file=${@: -1}
        set -- "${@:1:$(($#-1))}"
    fi
    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
}

यह काम किस प्रकार करता है। यह लाइन जांचती है कि क्या कम से कम एक तर्क है और यदि अंतिम तर्क एक फाइल है।

    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then

यह फ़ाइल को अलग तर्क में सहेजता है। चूंकि हम अंतिम तर्क को मिटाने वाले हैं।

        local file=${@: -1}

यहां हम अंतिम तर्क को हटाते हैं। चूंकि हम इसे एक तर्क के रूप में पारित नहीं करना चाहते हैं।

        set -- "${@:1:$(($#-1))}"

अंत में, हम जगा भाग करते हैं, तर्कों को पारित करते हुए (यदि यह फ़ाइल थी तो अंतिम तर्क को घटा देता है) जागरण में छाँटने के लिए। यह डेव द्वारा मौखिक रूप से सुझाया गया था, और क्रमबद्ध तर्क लेने के लिए संशोधित किया गया था। हम इस तथ्य पर भरोसा करते हैं कि $fileअगर हम पाइपिंग कर रहे हैं तो खाली हो जाएगा, इस प्रकार अनदेखा किया गया।

    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file

एक अल्पविराम से अलग फ़ाइल के साथ उदाहरण का उपयोग।

$ cat /tmp/test
A,B,C
0,1,2
1,2,0
2,0,1

# SORT NUMERICALLY SECOND COLUMN
$ skip_header_sort -t, -nk2 /tmp/test
A,B,C
2,0,1
0,1,2
1,2,0

# SORT REVERSE NUMERICALLY THIRD COLUMN
$ cat /tmp/test | skip_header_sort -t, -nrk3
A,B,C
0,1,2
2,0,1
1,2,0

0

अजगर के साथ:

import sys
HEADER_ROWS=2

for _ in range(HEADER_ROWS):
    sys.stdout.write(next(sys.stdin))
for row in sorted(sys.stdin):
    sys.stdout.write(row)

प्री-सपोसिट सिस्टम में पायथन को स्थापित किया गया है (मेरा नहीं है)
रॉब गिलियम

0

यहाँ अन्य उत्तरों से प्राप्त एक बैश शैल फ़ंक्शन है। यह फाइल और पाइप दोनों को हैंडल करता है। पहला तर्क फ़ाइल का नाम या '-' है। शेष तर्क को हल करने के लिए पारित किया जाता है। कुछ उदाहरण:

$ hsort myfile.txt
$ head -n 100 myfile.txt | hsort -
$ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r

खोल समारोह:

hsort ()
{
   if [ "$1" == "-h" ]; then
       echo "Sort a file or standard input, treating the first line as a header.";
       echo "The first argument is the file or '-' for standard input. Additional";
       echo "arguments to sort follow the first argument, including other files.";
       echo "File syntax : $ hsort file [sort-options] [file...]";
       echo "STDIN syntax: $ hsort - [sort-options] [file...]";
       return 0;
   elif [ -f "$1" ]; then
       local file=$1;
       shift;
       (head -n 1 $file && tail -n +2 $file | sort $*);
   elif [ "$1" == "-" ]; then
       shift;
       (read -r; printf "%s\n" "$REPLY"; sort $*);
   else
       >&2 echo "Error. File not found: $1";
       >&2 echo "Use either 'hsort <file> [sort-options]' or 'hsort - [sort-options]'";
       return 1 ;
   fi
}

0

यह इयान शेरबिन के उत्तर के समान है लेकिन मेरा कार्यान्वयन है: -

cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc
head -1 filetmp.tc > file.tc;
tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc;

-4
cat file_name.txt | sed 1d | sort 

यह वही करेगा जो आप चाहते हैं।


1) यह केवल हेडर लाइन को हटाता है और बाकी को छांटता है, यह हेडर लाइन के नीचे सब कुछ सॉर्ट नहीं करता है और हेडर बरकरार रहता है। 2) यह केवल पहली पंक्ति को हटाता है, जब हेडर वास्तव में दो लाइनें होती हैं (प्रश्न पढ़ें)। 3) आप "cat file_name.txt | sed 1d" का उपयोग क्यों करते हैं जब "sed 1d <file_name.txt" या यहां तक ​​कि "sed 1d file_name.txt" का भी समान प्रभाव होता है?
रोब गिलियम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.