मैं एक टेक्स्ट फ़ाइल (या स्टडिन) में लाइनों के क्रम को उल्टा करना चाहूंगा, प्रत्येक पंक्ति की सामग्री को संरक्षित करना।
तो, यानी, के साथ शुरू:
foo
bar
baz
मैं समाप्त करना चाहूंगा
baz
bar
foo
क्या इसके लिए एक मानक यूनिक्स कमांडलाइन उपयोगिता है?
मैं एक टेक्स्ट फ़ाइल (या स्टडिन) में लाइनों के क्रम को उल्टा करना चाहूंगा, प्रत्येक पंक्ति की सामग्री को संरक्षित करना।
तो, यानी, के साथ शुरू:
foo
bar
baz
मैं समाप्त करना चाहूंगा
baz
bar
foo
क्या इसके लिए एक मानक यूनिक्स कमांडलाइन उपयोगिता है?
जवाबों:
इसके अलावा उल्लेख के लायक: tac(ए, अहम, रिवर्स cat)। कोरुटिल का हिस्सा ।
tac a.txt > b.txt
brew install coreutils( gtacडिफ़ॉल्ट रूप से इंस्टॉल करता है)।
echo -n "abc\ndee" > test; tac test।
नहीं है अच्छी तरह से ज्ञात sed चाल :
# reverse order of lines (emulates "tac")
# bug/feature in HHsed v1.5 causes blank lines to be deleted
sed '1!G;h;$!d' # method 1
sed -n '1!G;h;$p' # method 2
(स्पष्टीकरण: बफर, स्वैप लाइन और बफर को पकड़ने के लिए गैर-प्रारंभिक लाइन को दबाएं, अंत में लाइन का प्रिंट आउट लें)
वैकल्पिक रूप से (तेज निष्पादन के साथ) एक-लाइनर्स से :
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*
अगर आपको याद नहीं है,
perl -e 'print reverse <>'
जीएनयू उपयोगिताओं के साथ एक प्रणाली पर, अन्य उत्तर सरल हैं, लेकिन सभी दुनिया जीएनयू / लिनक्स नहीं हैं ...
tail -rटैक नहीं ।
tacसे अपेक्षा की जाती है कि वे बड़ी-बड़ी फ़ाइलों को संभाल लें जो मेमोरी में फिट नहीं होती हैं (लाइन की लंबाई हालांकि अभी भी सीमित है)। यह स्पष्ट नहीं है कि क्या sedसमाधान ऐसी फ़ाइलों के लिए काम करता है।
आपके आदेश के अंत में:
| tac
tac वही करता है जो आप पूछ रहे हैं, यह "प्रत्येक FILE को मानक आउटपुट, अंतिम पंक्ति पहले लिखें।"
tac बिल्ली के विपरीत है :-)।
tacकमांड का मूल्य स्पष्ट करें , यह नए उपयोगकर्ताओं के लिए उपयोगी है जो एक ही विषय को खोज सकते हैं।
यदि आप vimउपयोग में होना है
:g/^/m0
$ (tac 2> /dev/null || tail -r)
कोशिश करें tac, जो लिनक्स पर काम करता है, और अगर वह काम नहीं करता है tail -r, जो बीएसडी और ओएसएक्स पर काम करता है।
tac myfile.txt- मैं क्या याद कर रहा हूँ?
tail -rमामले में वापस आने के लिए tacउपलब्ध नहीं है। tacPOSIX अनुरूप नहीं है। न ही है tail -r। फिर भी मूर्ख नहीं है, लेकिन यह काम करने की बाधाओं को सुधारता है।
tacउपलब्ध हो तो क्या होता है, लेकिन रैम से बाहर चला जाता है और एक विशाल इनपुट स्ट्रीम का उपभोग करके आधे रास्ते को स्वैप करता है। यह विफल हो जाता है, और फिर tail -rएक गलत परिणाम देने वाली शेष धारा को संसाधित करने में सफल होता है।
brew install coreutils और उपयोग gtacके स्थान पर tacऔर यदि आपके लिए एक उपनाम के रूप में जोड़ने के टैक पसंद करते हैं gtac, तो उदाहरण के लिए यदि आप एक खोल स्क्रिप्ट है कि यह पार मंच (लिनक्स, OSX) का इस्तेमाल किया चाहता था
निम्नलिखित कमांड आज़माएं:
grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"
sed 's/^[0-9]*://g'
nlडिफ़ॉल्ट रूप से खाली लाइनों की संख्या में विफल हो जाएगा। -baविकल्प, कुछ सिस्टम पर उपलब्ध है नहीं सार्वभौमिक नहीं है (हालांकि मैं चाहता हूँ ऐसा नहीं है एचपी / UX, मन में आता है) जबकि grep -nहमेशा संख्या हर लाइन है कि (इस मामले में खाली) regex से मेल खाता।
cut -d: -f2-
बस बैश :) (4.0+)
function print_reversed {
local lines i
readarray -t lines
for (( i = ${#lines[@]}; i--; )); do
printf '%s\n' "${lines[i]}"
done
}
print_reversed < file
-neneneneneneneऔर इस कारण को देखें कि लोग हमेशा की printf '%s\n'बजाय इस्तेमाल करने की सलाह देते हैं echo।
सरलतम विधि tacकमांड का उपयोग कर रही है । tacका catविलोम है। उदाहरण:
$ cat order.txt
roger shah
armin van buuren
fpga vhdl arduino c++ java gridgain
$ tac order.txt > inverted_file.txt
$ cat inverted_file.txt
fpga vhdl arduino c++ java gridgain
armin van buuren
roger shah
मुझे वास्तव में " टेल-आर " उत्तर पसंद है, लेकिन मेरा पसंदीदा गॉक उत्तर है ...।
gawk '{ L[n++] = $0 }
END { while(n--)
print L[n] }' file
mawkUbuntu 14.04 LTS पर - काम करता है, तो यह जीएनयू awk विशिष्ट नहीं है। +1
n++के साथ प्रतिस्थापित किया जा सकता हैNR
निम्नलिखित को संपादित करें 1 से 10 तक की संख्याओं की एक क्रमबद्ध क्रमबद्ध सूची बनाता है:
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') **...**
जहां डॉट्स को वास्तविक कमांड से बदल दिया जाता है जो सूची को उलट देता है
टैक
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(tac)
अजगर: sys.stdin पर [:: - 1] का उपयोग करना
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(python -c "import sys; print(''.join(([line for line in sys.stdin])[::-1]))")
क्रॉस ओएस (यानी ओएसएक्स, लिनक्स) समाधान के लिए जो उपयोग कर सकता है tac शेल स्क्रिप्ट के अंदर हैं होमब्रे का उपयोग करें जैसा कि दूसरों ने ऊपर उल्लेख किया है, तो बस उर्फ टैक जैसे:
लिब स्थापित करें
MacOS के लिए
brew install coreutils
लिनक्स डेबियन के लिए
sudo apt-get update
sudo apt-get install coreutils
फिर उपनाम जोड़ें
echo "alias tac='gtac'" >> ~/.bash_aliases (or wherever you load aliases)
source ~/.bash_aliases
tac myfile.txt
यदि आप फ़ाइल को जगह में बदलना चाहते हैं, तो आप चला सकते हैं
sed -i '1!G;h;$!d' filename
यह एक अस्थायी फ़ाइल बनाने की आवश्यकता को हटा देता है और फिर मूल को हटा या नाम बदल देता है और उसी का परिणाम होता है। उदाहरण के लिए:
$tac file > file2
$sed -i '1!G;h;$!d' file
$diff file file2
$
एपिमिएंट के उत्तर के आधार पर , जो लगभग नहीं, बल्कि काफी था, जो मैं चाहता था।
मेरे साथ ऐसा होता है कि मैं nएक बहुत बड़ी पाठ फ़ाइल की अंतिम पंक्तियों को कुशलता से प्राप्त करना चाहता हूं ।
मैंने जो पहली कोशिश की वह है tail -n 10000000 file.txt > ans.txt, लेकिन मुझे यह बहुत धीमा लगा, इसके लिएtail स्थान तलाशना पड़ा और फिर परिणाम छापने के लिए वापस चला गया।
जब मुझे इसका एहसास होता है, तो मैं दूसरे समाधान पर जाता हूं tac file.txt | head -n 10000000 > ans.txt:। इस बार, तलाश की स्थिति को अंत से वांछित स्थान पर जाने की आवश्यकता है और यह 50% समय बचाता है !
घर संदेश ले:
tac file.txt | head -n nयदि आपके tailपास -rविकल्प नहीं है तो उपयोग करें ।
सबसे अच्छा उपाय:
tail -n20 file.txt | tac
Emacs उपयोगकर्ताओं के लिए: C-x h(पूरी फ़ाइल का चयन करें) और फिर M-x reverse-region। इसके अलावा केवल भागों या लाइनों का चयन करने और उन लोगों को पुनः प्राप्त करने के लिए काम करता है।
मेरा भी यही सवाल था, लेकिन मैं भी चाहता था कि पहली पंक्ति (हेडर) शीर्ष पर बनी रहे। तो मुझे जाग की शक्ति का उपयोग करने की आवश्यकता थी
cat dax-weekly.csv | awk '1 { last = NR; line[last] = $0; } END { print line[1]; for (i = last; i > 1; i--) { print line[i]; } }'
PS साइबरविन या जीटबैश में भी काम करता है
1\n20\n19...2\nबजाय परिणाम प्रतीत होता है 20\n19...\2\n1\n।
आप इसके साथ vim stdinऔर कर सकते हैं stdout। तुम भी POSIX आज्ञाकारीex होने के लिए उपयोग कर सकते हैं । के लिए सिर्फ दृश्य विधा है । वास्तव में, आप उपयोग कर सकते हैं के साथ या (सुधार मोड)।
उपयोगी है क्योंकि इसके विपरीत उपकरण जैसे कि यह संपादन के लिए फ़ाइल को बफ़र करता है, जबकि इसका उपयोग स्ट्रीम के लिए किया जाता है। आप उपयोग करने में सक्षम हो सकते हैं , लेकिन आपको एक चर में मैन्युअल रूप से सब कुछ बफर करना होगा।vimexexvim -evim -Eexvimsedsedawk
विचार निम्नलिखित करना है:
g/^/m0। इसका अर्थ है विश्व स्तर पर, प्रत्येक पंक्ति के लिए g; लाइन की शुरुआत से मेल खाता है, जो किसी भी चीज से मेल खाता है ^; पता 0 के बाद इसे स्थानांतरित करें, जो पंक्ति 1 हैm0 ।%p। इसका मतलब सभी लाइनों की सीमा के लिए है %; लाइन प्रिंट करें p।q!। इसका मतलब छोड़ दिया q; जबरदस्ती !।# Generate a newline delimited sequence of 1 to 10
$ seq 10
1
2
3
4
5
6
7
8
9
10
# Use - to read from stdin.
# vim has a delay and annoying 'Vim: Reading from stdin...' output
# if you use - to read from stdin. Use --not-a-term to hide output.
# --not-a-term requires vim 8.0.1308 (Nov 2017)
# Use -E for improved ex mode. -e would work here too since I'm not
# using any improved ex mode features.
# each of the commands I explained above are specified with a + sign
# and are run sequentially.
$ seq 10 | vim - --not-a-term -Es +'g/^/m0' +'%p' +'q!'
10
9
8
7
6
5
4
3
2
1
# non improved ex mode works here too, -e.
$ seq 10 | vim - --not-a-term -es +'g/^/m0' +'%p' +'q!'
# If you don't have --not-a-term, use /dev/stdin
seq 10 | vim -E +'g/^/m0' +'%p' +'q!' /dev/stdin
# POSIX compliant (maybe)
# POSIX compliant ex doesn't allow using + sign to specify commands.
# It also might not allow running multiple commands sequentially.
# The docs say "Implementations may support more than a single -c"
# If yours does support multiple -c
$ seq 10 | ex -c "execute -c 'g/^/m0' -c '%p' -c 'q!' /dev/stdin
# If not, you can chain them with the bar, |. This is same as shell
# piping. It's more like shell semi-colon, ;.
# The g command consumes the |, so you can use execute to prevent that.
# Not sure if execute and | is POSIX compliant.
seq 10 | ex -c "execute 'g/^/m0' | %p | q!" /dev/stdin
इस पुन: प्रयोज्य बनाने के लिए कैसे
मैं एक स्क्रिप्ट का उपयोग करता हूं जिसे मैं कॉल करता हूं ved(जैसे विम संपादक sed) संपादित करने के लिए विम का उपयोग करने के लिए stdin। इसे vedअपने पथ में नामक फ़ाइल में जोड़ें :
#!/usr/bin/env sh
vim - --not-a-term -Es "$@" +'%p | q!'
मैं +इसके बजाय एक कमांड का उपयोग कर रहा हूं +'%p' +'q!', क्योंकि विम आपको 10 कमांड तक सीमित करता है। इसलिए उन्हें विलय "$@"करने से 9 की अनुमति मिलती है+ करने से 8 के बजाय कमांड रखने की ।
तो आप कर सकते हैं:
seq 10 | ved +'g/^/m0'
यदि आपके पास 8 विम नहीं है, तो इसे vedइसके स्थान पर रखें:
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
rev
text here
या
rev <file>
या
rev texthere
sort -r < filename
या
rev < filename
sort -rकेवल तभी काम करता है जब इनपुट पहले से ही सॉर्ट किया गया हो, जो यहां नहीं है। revप्रति पंक्ति वर्णों को उलट देता है लेकिन रेखा के क्रम को अक्षुण्ण रखता है जो कि स्कूटी ने नहीं पूछा था। तो यह जवाब वास्तव में कोई जवाब नहीं है।
perl -e 'print reverse <>'लेकिन यह संभवतः अन्य तरीकों पर भी लागू होता है)।