किसी फ़ाइल में लाइनों का क्रम बदलें


11

मैं एक विशिष्ट पैटर्न में लाइनों के क्रम को बदलने की कोशिश कर रहा हूं। कई पंक्तियों वाली फ़ाइल के साथ कार्य करना (उदा। 99 पंक्तियाँ)। प्रत्येक तीन पंक्तियों के लिए, मैं दूसरी पंक्ति को तीसरी पंक्ति और तीसरी पंक्ति को दूसरी पंक्ति बनाना चाहूंगा।

उदाहरण।

1- इनपुट:

gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...

2- आउटपुट:

gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...

जवाबों:


12

awkगणित का उपयोग और पूर्णांक:

awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay } }' /path/to/input

मापांक ऑपरेटर पूर्णांक विभाजन करता है और शेष को लौटाता है, इसलिए प्रत्येक पंक्ति के लिए, यह अनुक्रम 1, 2, 0, 1, 2, 0 [...] को लौटाएगा। यह जानते हुए कि, हम इनपुट को उन लाइनों पर सहेजते हैं जहाँ मापांक बाद में 2 के लिए है - बुद्धि के लिए, इनपुट को मुद्रण के बाद जब यह शून्य हो।


हमारे यहाँ एक छोटी सी खामी है। मेरा जवाब देखिए, मामूली सुधार वाला हिस्सा
सर्जियो कोलोडियाज़नी

अच्छी पकड़ के लिए धन्यवाद; मैंने अपने उत्तर में एक फिक्स को शामिल किया है NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
डोपघोटी

23
$ seq 9 | sed -n 'p;n;h;n;G;p'
1
3
2
4
6
5
7
9
8

यही है, pवर्तमान लाइन को रिंट करें, पूर्व को प्राप्त करें n, hइसे पुराना करें, पूर्व को प्राप्त करें n, Gएट लाइन को ले जाएं (इसे पैटर्न स्पेस में जोड़ें) और pरिंट करें कि तीसरी और दूसरी लाइन के साथ 2-लाइन पैटर्न स्पेस स्वैप किया गया।


3

एक और जाग दृष्टिकोण:

awk '{print $0; if ((getline L2)>0 && (getline L3)>0){ print L3 ORS L2 }}' file

उत्पादन:

gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

  • (getline L2)>0 && (getline L3)>0- अगर वे मौजूद हैं तो अगले 2 रिकॉर्ड निकालते हैं

  • प्रत्येक 2 और 3 रिकॉर्ड क्रमशः के लिए L2और L3चर को सौंपा गया है


1
मैं मान रहा हूँ कि ये अक्षर L (लोअर केस) अक्षर से शुरू होते हैं। वे पठनीयता के लिए खराब विकल्प हैं क्योंकि वे बारह और तेरह के लिए अंकों की तरह दिखते हैं। एक बेहतर विकल्प हो सकता है line2, आदि
आगे की सूचना तक रोक दिया गया।

@ डेनिसविलियम्सन, अपरकेस में बदल गया
रोमनपेरेरेस्ट

1

perlएक स्क्रिप्ट का उपयोग और

user@pc:~$ cat input.txt 
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.

user@pc:~$ perl -ne '$l2=<>; $l3=<>; print $_,$l3,$l2;' input.txt 
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

स्क्रिप्ट पूरी फ़ाइल को संसाधित करती है, प्रत्येक पंक्ति के लिए (इसमें संग्रहीत $_) यह अगली दो लाइनें ( $l2और $l3) प्राप्त करेगा और उन्हें अनुरोधित क्रम में प्रिंट करेगा: लाइन 1, लाइन 3, लाइन 2।


1

एक तरीका इस प्रकार हो सकता है:

sed -e '
   /\n/s/\(.*\)\(\n\)\(.*\)/\3\2\1/;//b
   $!N;$q;N;                            # load up the pattern space with 3 lines provided eof not reached
   P;D;                                 # first just print the first line then interchange the two and print them
' yourfile

वैकल्पिक रूप से,

perl -ne 'print $_, reverse scalar <>, scalar <>' yourfile

परिणाम

gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

1

सिर्फ थोड़ी देर का लूप क्यों नहीं? विस्तारित रूप में:

( while read a
  do
    read b
    read c
    echo "$a"
    echo "$c"
    echo "$b"
  done
) < input.txt

"एकल पंक्ति प्रारूप" में:

( while read a ; do read b ; read c ; echo "$a" ; echo "$c" ; echo "$b" ; done) < input.txt

आउटपुट:

gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

1

पर्ल

perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt

यहां विचार यह है कि हम %लाइन नंबर $.चर के साथ मॉडुलो ऑपरेटर का उपयोग करते हैं , यह पता लगाने के लिए कि कौन सा प्रत्येक पहले है, कौन सा प्रत्येक दूसरा है, और कौन सा प्रत्येक 3 लाइन है। प्रत्येक तीसरी पंक्ति के लिए शेष 0 है, जबकि प्रत्येक 1 और 2 पंक्ति के लिए इसकी संख्या समान होगी।

परीक्षा:

$ cat input.txt                                                                                                          
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.

$ perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt                                    
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

मामूली सुधार

एक चर में दूसरी पंक्ति के भंडारण के दृष्टिकोण में दोष है। क्या होगा यदि अंतिम पंक्ति "दूसरी" एक है, अर्थात उस पंक्ति की शेष संख्या 2 है? मेरे और डोपगोटी के उत्तर में मूल कोड प्रिंट नहीं होगा My dog is orangeयदि हम अंतिम पंक्ति को छोड़ देते हैं। दोनों मामलों में इसके लिए फिक्स END{}कोड ब्लॉक का उपयोग करना है , मुद्रण के बाद अस्थायी चर को परेशान करने के साथ। दूसरे शब्दों में:

$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt

तथा

$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt 

इस तरह, कोड एक फ़ाइल में मनमानी संख्या के लिए काम करेगा, न कि 3 से विभाज्य।

टिप्पणियों में उल्लिखित मुद्दे के लिए अतिरिक्त फिक्स

Awk के मामले में, यदि फ़ाइल में अंतिम पंक्ति $ 1 के आउटपुट का उत्पादन करती है। % 3, पिछले कोड में बिना शर्त के मुद्रण के कारण रिक्त न्यूलाइन को आउटपुट करने का मुद्दा है END{print delay}, क्योंकि printटिप्पणियों में उल्लेखित फ़ंक्शन हमेशा न्यूलाइन को जो भी चर पर चल रहा है, को जोड़ देता है। perlसंस्करण के मामले में यह समस्या नहीं होती है, क्योंकि -neझंडे printसमारोह के साथ नई रेखा को जोड़ते नहीं हैं।

फिर भी, awk के मामले में सुधार सशर्त बनाना है, जैसा कि टिप्पणियों में डोप घोटी ने उल्लेख किया है, अस्थायी चर की लंबाई को सत्यापित करना है। समान फिक्स का पर्ल संस्करण होगा:

$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt 

1
आपके फिक्स की अपनी स्वयं की संभावित छोटी खामी है कि यह 'गलत' लाइनों की संख्या के साथ फाइलों के लिए आउटपुट की एक रिक्त रेखा को जोड़ देगा। मैंने (मेरे लिए awk) मेरे उत्तर में आपके सुधार के समावेश में इसे निर्धारित किया है NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
डोपघोटी

1
@DopeGhoti समस्या पर्ल के साथ नहीं होती है, क्योंकि -neझंडे के साथ पर्ल का प्रिंट एक नई पंक्ति का उत्पादन नहीं करता है। यह वास्तव में प्रिंट करता है, लेकिन यह एक अशक्त स्ट्रिंग है, कोई अनुगामी न्यूलाइन नहीं है। बहरहाल, मैंने इस मुद्दे का उल्लेख और मेरे उत्तर में एक ही तय किया है। धन्यवाद !
सर्गी कोलोडाज़नी

1

शक्ति

लंबी फ़ाइलों के लिए उपयुक्त नहीं है, लेकिन फिर भी अगर आप सिर्फ एक फ़ाइल को संपादित कर रहे थे और उदाहरण के लिए, कुछ याम्यल श्लोक को पुनः व्यवस्थित करना चाहते थे।

पहले एक मैक्रो रिकॉर्ड करें:

gg qq j ddp j q

और फिर वांछित संख्या को दोहराएं:

@q @q @q ...

या सिर्फ उदा

3@q

स्पष्टीकरण:

  • gg - पहली पंक्ति पर जाएं
  • qq - एक मैक्रो रिकॉर्ड करना शुरू करें
  • j - दूसरी लाइन पर जाएं
  • ddp - दूसरी और तीसरी पंक्ति को स्वैप करें
  • j - चौथी लाइन पर जाएं, यानी अगली तीन लाइनों में से पहली पंक्ति में
  • q - रिकॉर्डिंग बंद करो
  • @q - मैक्रो को एक बार रीप्ले करें
  • 3 @ q - तीन बार मैक्रो को फिर से चलाएँ

1
मैनुअल दोहराने के बजाय @q @q @q, यह इस तरह से करना संभव है 3@q- तीन बार दोहराएं। 100@q- मैक्रो को 100 बार दोहराएं।
मिनीमैक्स

0

उपयोग: ./shuffle_lines.awk input.txt

शेबबैंग की जांच करें #!/usr/bin/awk -f, क्योंकि awkआपके सिस्टम पर स्थान भिन्न हो सकता है।

#!/usr/bin/awk -f

{
    if ((NR + 1) % 3 == 0) {
        buffer = $0;
    } else if (NR % 3 == 0) {
        print $0 ORS buffer;
        buffer = "";
    } else {
        print;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.