अस्थायी फ़ाइल का उपयोग किए बिना आउटपुट की पहली एन लाइनों को समाप्त करें


11

जैसे कमांड के आउटपुट की कल्पना करें

44444
55555
11111
22222
33333

मैं पहली एन लाइनों (ऊपर उदाहरण में पहले दो) को कैसे समाप्त कर सकता हूं और उन्हें अंत में जोड़ सकता हूं, लेकिन बिना अस्थायी फ़ाइल (इसलिए केवल पाइप का उपयोग करके)?

11111
22222
33333
44444
55555

की तर्ज पर कुछ | sed -n '3,5p;1,2p'(जो स्पष्ट रूप से sed के रूप में काम नहीं करता है, कमांड के आदेश की परवाह नहीं करता है)।


2
हम एक अस्थायी फ़ाइल का उपयोग क्यों नहीं कर सकते हैं?
ब्रायम

जवाबों:


13

बस उन पंक्तियों को होल्ड बफर पर कॉपी करें (फिर उन्हें डिलीट करें) और जब आखिरी लाइन पर होल्ड बफर की सामग्री को पैटर्न स्पेस में जोड़ें:

some command | sed '1,NUMBER{           # in this range
H                                       # append line to hold space and
1h                                      # overwrite if it's the 1st line
d                                       # then delete the line
}
$G'                                     # on last line append hold buffer content

के साथ gnu sedआप इसे लिख सकते हैं

some command | sed '1,NUMBER{H;1h;d;};$G'

यहाँ ol के साथ एक और तरीका है ed(यह पाठ बफ़र rके आउटपुट some commandको मिटा देता है और फिर la t one के बाद mअंडाकार लाइनों 1,NUMBERको $):

ed -s <<IN
r ! some command
1,NUMBERm$
,p
q
IN

ध्यान दें - जैसा कि बताया गया है - ये दोनों विफल हो जाएंगे यदि आउटपुट में NUMBER+1 लाइनें कम हैं। एक अधिक ठोस दृष्टिकोण होगा ( gnu sedवाक्य रचना):

some command | sed '1,NUMBER{H;1h;$!d;${g;q;};};$G'

यह केवल तब तक उस सीमा में लाइनों को हटाता है जब तक वे अंतिम पंक्ति ( $!d) नहीं होते हैं - अन्यथा यह बफर सामग्री ( g) और फिर qयूआईटी (वर्तमान पैटर्न स्थान को प्रिंट करने के बाद ) के साथ पैटर्न स्पेस को ओवरराइट करता है ।


2
sed -e '1,NUMBER{H;1h;d;}' -e '$G'यह भी सुस्पष्ट रूप से काम करता है (ध्यान दें कि कुछ sedकार्यान्वयन होल्ड स्पेस में कुछ किलोबाइट से अधिक नहीं पकड़ सकते हैं, इसलिए NUMBER वहां बहुत बड़ा नहीं हो सकता है)
स्टीफन चेज़लस

@ स्टीफनचेलजेलस - इनपुट के लिए धन्यवाद - मैं आमतौर पर प्रति पंक्ति एक कमांड के साथ जाता हूं जैसा कि मुझे पता है कि पोर्टेबल है - कई अभिव्यक्ति वाक्यविन्यास हमेशा मेरे लिए थोड़ा भ्रमित रहा है जैसे कि पॉज़िक्स डॉक्स कहते हैं "द राइट-ब्रेस" एक <newline> "से पहले तो उनके अनुसार ऐसा नहीं होना चाहिए sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'?
don_crissti

4
आमतौर पर, एक नया एक नया -eस्थान बदलता है। d;}अभी तक POSIX नहीं है लेकिन पोर्टेबल है। यह अगले POSIX कल्पना में तय किया जाएगा। देखें austingroupbugs.net/view.php?id=944#c2720
स्टीफन Chazelas

2
@don_crissti धन्यवाद! यह अच्छा होगा यदि आप यह क्यों काम करता है की एक छोटी व्याख्या भी शामिल कर सकते हैं। (बेशक मैं इसे देखने जाऊँगा, लेकिन यह अधिक मूल्यवान उत्तर के लिए
बनायेगा

मेरे सिर में, unportable चीज़ के बारे में 1,NUMBER{H;1h;d;}एक अर्धविराम के तुरंत बाद होने नहीं कर रहा है उद्घाटन ब्रेस। यह सिर्फ सनोस 4.1 में एक बग हो सकता है sedजिसका वर्कअराउंड 20 साल बाद भी मेरी अंगुलियों में है, हालांकि।
zwol

11

एक awkदृष्टिकोण:

cmd | awk -v n=3 '
  NR <= n {head = head $0 "\n"; next}
  {print}
  END {printf "%s", head}'

@ Don_crissti के sedदृष्टिकोण से एक लाभ यह है कि यह अभी भी काम करता है (लाइनों को आउटपुट करता है) यदि आउटपुट में nलाइनें या कम हैं।


आप \nओआरएस के साथ हार्डकोड को बदलना चाह सकते हैं , ताकि यह अन्य रिकॉर्ड विभाजकों के साथ काम करे (जैसे कि आप पैराग्राफ आदि का उपयोग करना चाहते हैं)।
फेडोरक्वि

6

मेरे पास है xclipऔर इसके साथ इस तरह से किया जा सकता है:

./a_command | xclip -in && xclip -o | tail -n +3 && xclip -o | head -n 2

यहाँ इसका वर्णन है:

xclip - command line interface to X selections (clipboard)

NAME
       xclip - command line interface to X selections (clipboard)

SYNOPSIS
       xclip [OPTION] [FILE]...

DESCRIPTION
       Reads from standard in, or from one or more files, and makes the data available as an X selection for pasting into X applications. Prints current X selection to standard out.

       -i, -in
              read text into X selection from standard input or files (default)

       -o, -out
              prints the selection to standard out (generally for piping to a file or program)

3
X के रचनात्मक (गलत-) उपयोग के लिए +1। उत्तर को एक सुलभ / चल रहे एक्स सर्वर की आवश्यकता है।
जोफेल

3

एक पर्ल तरीका:

perl -ne '$.<3?($f.=$_):print;}{print $f'

या, एक ही चीज़ को कम से कम लिखित रूप से:

perl -ne 'if($.<3){ $f.=$_ } else{ print } END{print $f}'

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

$ cat file
44444
55555
11111
22222
33333

$ cat file | perl -ne '$.<3?($f.=$_):print;}{print $f'
11111
22222
33333
44444
55555

व्याख्या

  • -ne: लाइन द्वारा इनपुट फ़ाइल / स्ट्रीम लाइन पढ़ें और -eप्रत्येक लाइन द्वारा दी गई स्क्रिप्ट को लागू करें ।
  • $.<3: $.वर्तमान लाइन नंबर है, इसलिए 3उन लाइनों की संख्या में परिवर्तन करें जिन्हें आप स्थानांतरित करना चाहते हैं।
  • $.<3?($f.=$_):print;: इस सशर्त ऑपरेटर है, सामान्य स्वरूप है condition ? case1 : case2, यह चलेगा case1अगर conditionसच है और case2अगर यह गलत है। यहां, यदि वर्तमान लाइन संख्या 3 से कम है, तो यह वर्तमान लाइन ( $_) को चर में जोड़ता है $fऔर, यदि लाइन संख्या 3 से अधिक है, तो यह प्रिंट करता है।
  • }{ print $f: के }{लिए पर्ल शॉर्टहैंड है END{}। यह सभी इनपुट लाइनों के संसाधित होने के बाद चलेगा। इस बिंदु पर, हमने उन सभी लाइनों को एकत्र किया है जिन्हें हम स्थानांतरित करना चाहते हैं और उन सभी को मुद्रित करेंगे जिन्हें हम अकेले छोड़ना चाहते हैं, इसलिए सहेजी गई रेखाओं को प्रिंट करें $f

1
आपके गोल्फ संस्करण के बारे में कुछ चरित्र को हटाया जा सकता हैperl -ne '$.<3?$f.=$_:print}{print $f
123

1

POSIX का उपयोग करें ex। हां, यह फ़ाइल संपादन के लिए है, लेकिन यह एक पाइपलाइन में काम करेगा।

printf %s\\n 111 222 333 444 555 | ex -sc '1,2m$|%p|q!' /dev/stdin

यह पाइपलाइन की शुरुआत या अंत में जोड़ा गया कोई भी मनमाना आदेश हो सकता है और वही काम करेगा। बेहतर अभी तक, की उपस्थिति को देखते हुए /dev/stdin, यह POSIX आज्ञाकारी है।

(मुझे नहीं पता कि /dev/stdinPOSIX में निर्दिष्ट है या नहीं, लेकिन मुझे लगता है कि यह लिनक्स और मैक ओएस एक्स दोनों में मौजूद है)

इसका sedस्थान के उपयोग पर एक पठनीयता लाभ है - आप बस ex"इन पंक्तियों को अंत तक ले जाएँ" और यह ऐसा करता है। (शेष आदेशों का अर्थ है "बफर को प्रिंट करें" और "बाहर निकलें," जो कि काफी पठनीय हैं।)

NB: exयदि इनपुट के रूप में 2 से कम लाइनें दी गई हैं, तो ऊपर दी गई कमांड विफल हो जाएगी।

आगे की पढाई:


0

एक छोटा सा pythonस्निपेट:

#!/usr/bin/env python3
import sys
file_ = sys.argv[1]
lines = int(sys.argv[2])
with open(file_) as f:
    f = f.readlines()
    out = f[lines:] + f[:lines]
    print(''.join(out), end='')

प्रथम तर्क के रूप में फ़ाइलनाम पास करें और दूसरे तर्क के रूप में स्थानांतरित करने के लिए लाइनों की संख्या।

उदाहरण:

$ cat input.txt
44444
55555
11111
22222
33333

$ ./sw_lines.py input.txt 2
11111
22222
33333
44444
55555

$ ./sw_lines.py input.txt 4
33333
44444
55555
11111
22222

0

यदि आप पूरे आउटपुट को मेमोरी में स्टोर कर सकते हैं:

data=$(some command)
n=42                  # or whatever
{ tail -n +$((n+1)) <<<"$data"; head -n $n <<<"$data"; } > outputfile

0

यहाँ एक और विकल्प है जिसके लिए GNU की आवश्यकता है sed:

(x=$(gsed -u 3q);cat;printf %s\\n "$x")

-uGNU को sedअसंबद्ध बनाता है ताकि sedकमांड STDIN की 3 से अधिक लाइनों का उपभोग न करे। कमांड प्रतिस्थापन खाली लाइनों को हटाता है, ताकि कमांड तीसरे, तीसरे और दूसरे या तीसरे, दूसरे और पहले लाइनों के खाली होने पर आउटपुट के अंत में खाली लाइनों को शामिल न करे।

आप भी कुछ ऐसा कर सकते हैं:

tee >(sponge /dev/stdout|sed -u 3q)|sed 1,3d

बिना sponge /dev/stdout|कमांड लंबे इनपुट्स के साथ फेल हो जाएगा। sponge /dev/stdoutभी साथ बदला जा सकता tac|tacहै, भले ही उदाहरण के लिए है कि प्रिंट a\ncbइनपुट है अगर a\nb\ncजहां \nएक linefeed है, या के साथ (x=$(cat);printf %s\\n "$x"), भले ही है कि हटा देगा रिक्त इनपुट के अंत से लाइनों। ऊपर की कमांड पहली पंक्ति को हटा देती है जब इनपुट की लाइनों की संख्या एक या दो होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.