किसी चर की सामग्री को शब्दों द्वारा उलट देना


13

तो अगर मुझे एक चर मिल गया है

VAR='10 20 30 40 50 60 70 80 90 100'

और इसे बाहर गूंज

echo "$VAR"
10 20 30 40 50 60 70 80 90 100

हालाँकि, स्क्रिप्ट के आगे मुझे इस चर के क्रम को उलटने की आवश्यकता है इसलिए यह कुछ इस तरह दिखाता है

echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10

मैंने रेव का उपयोग करने की कोशिश की और यह सचमुच सब कुछ उलट गया, इसलिए यह बाहर आया

echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01

2
इस तरह के प्रश्न के उत्तर में आपको कुछ उपयोगी सुझाव मिल सकते हैं: आईपी ​​एड्रेस को पीछे की ओर कैसे पढ़ें? (सिर्फ पीरियड्स की जगह स्पेस
सेपरेटर्स के

जवाबों:


21

GNU सिस्टम पर, बिल्ली का उल्टा tac है:

$ tac -s" " <<< "$VAR "            # Please note the added final space.
100 90 80 70 60 50 40 30 20 10

चीयर्स! यही चाल चली। मुझे अभी भी बहुत कुछ सीखने को मिला है
एलिस्टेयर हार्डी

@ जोंकगेलमैन गूंज के बिना, आउटपुट के पास एक अतिरिक्त नई रेखा है, इसके बराबर:echo $'100 \n90 80 70 60 50 40 30 20 10'
sorontar

वर्तमान tac -s" " <<< "$VAR "संस्करण के साथ, यह अभी भी एक अग्रणी रिक्त लाइन सम्मिलित करता है, एक अनुगामी स्थान जोड़ता है और अनुगामी न्यूलाइन वर्ण (जैसे कि printf '\n%s ' "$reversed_VAR"अपेक्षित के बजाय printf '%s\n' "$reversed_VAR") को छोड़ देता है
स्टीफन चेज़लस

@don_crissti मूल उत्तर: के echo $(tac -s" " <<< $VAR)पास एक अनुगामी स्थान नहीं है क्योंकि $(…)नई अनुगामी और रिक्त स्थान को हटाता है यदि IFS उनके पास है। मेरा समाधान जल्द ही सही हो जाएगा, धन्यवाद।
सोरोंटर

6

एक छोटी सूची के लिए, और एक चर में, शेल स्वयं सबसे तेज़ समाधान है:

var="10 20 30 40 50 60 70 80 90 100"
set -- $var; unset a 
for ((i=$#;i>0;i--)); do
    printf '%s%s' "${a:+ }" "${!i}"
    a=1
done
echo

आउटपुट:

100 90 80 70 60 50 40 30 20 10 

ध्यान दें: में विभाजित ऑपरेशन set -- $varयहां उपयोग किए जाने वाले सटीक स्ट्रिंग के लिए सुरक्षित है, लेकिन स्ट्रिंग वाइल्डकार्ड वर्ण ( *, ?या []) में है तो ऐसा नहीं होगा । set -fजरूरत पड़ने पर बंटवारे से पहले इससे बचा जा सकता है । एक ही नोट निम्नलिखित समाधानों के लिए भी मान्य है (जहां नोट किया गया है)।

या, यदि आप रिवर्स सूची के साथ कुछ अन्य चर सेट करना चाहते हैं:

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
for i; do out="$i${out:+ }$out"; done
echo "$out"

या केवल स्थितीय मापदंडों का उपयोग करना।

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
a=''
for    i
do     set -- "$i${a:+ $@}"
       a=1
done
echo "$1"

या केवल एक चर (जो स्वयं ही हो सकता है) का उपयोग कर:
नोट: यह समाधान ग्लोब से प्रभावित नहीं है और न ही IFS।

var="10 20 30 40 50 60 70 80 90 100"

a=" $var"
while [[ $a ]]; do
    printf '<%s>' "${a##* }"
    var="${a% *}"
done

2

awk बचाव के लिए

$ var='10 20 30 40 50 60 70 80 90 100'

$ echo "$var" | awk '{for(i=NF; i>0; i--) printf i==1 ? $i"\n" : $i" "}'
100 90 80 70 60 50 40 30 20 10


के साथ perl, शिष्टाचार एक आईपी पते को पीछे की ओर कैसे पढ़ें? @steeldriver द्वारा साझा किया गया

$ echo "$var" | perl -lane '$,=" "; print reverse @F'
100 90 80 70 60 50 40 30 20 10


या, bashस्ट्रिंग को सरणी में परिवर्तित करके स्वयं के साथ

$ arr=($var)    
$ for ((i=${#arr[@]}-1; i>=0; i--)); do printf "${arr[i]} "; done; echo
100 90 80 70 60 50 40 30 20 10 

2

आप इसे पूरी तरह से प्रक्रिया में करने के लिए सरणियों जैसे बैश सुविधाओं का उपयोग कर सकते हैं:

#!/bin/bash
VAR="10 20 30 40 50 60 70 80 90 100"
a=($VAR); rev_a=()
for ((i=${#a[@]}-1;i>=0;i--)); do rev_a+=( ${a[$i]} ); done; 
RVAR=${rev_a[*]}; 

यह करने का सबसे तेज़ तरीका होना चाहिए, बशर्ते कि $ VAR बहुत बड़ा न हो।


हालांकि यह उन चरों के लिए नहीं है जिनके मूल्य में वाइल्डकार्ड वर्ण (जैसे VAR='+ * ?') हैं। का उपयोग करें set -o noglobया set -fठीक करने के लिए। अधिक आम तौर पर, $IFSविभाजन + ग्लोब ऑपरेटर का उपयोग करते समय ग्लोबिंग के मूल्य और स्थिति पर विचार करना एक अच्छा विचार है । ऐसा नहीं है कि यह उस ऑपरेटर का उपयोग करने के लिए बहुत कम समझ में आता है rev_a+=( ${a[$i]} ), rev_a+=( "${a[$i]}" )बहुत अधिक समझ में आता है।
स्टीफन चेजेलस


1

यहाँ अजगर जादू का थोड़ा प्रयोग करें:

bash-4.3$ VAR='10 20 30 40 50 60 70 80 90 100'
bash-4.3$ python -c 'import sys;print " ".join(sys.argv[1].split()[::-1])'  "$VAR" 
100 90 80 70 60 50 40 30 20 10

जिस तरह से यह काम काफी सरल है:

  • हम "$VAR"दूसरी कमांड लाइन पैरामेंटर के रूप में संदर्भित करते हैं sys.argv[1]( -cविकल्प के साथ पहला पैरामीटर हमेशा बस यही होता है - -cस्वयं। "$VAR"चर को अलग-अलग शब्दों में विभाजित करने से रोकने के लिए चारों ओर ध्यान दें।
  • अगला हम .split()विधि का उपयोग करते हैं, इसे स्ट्रिंग्स की सूची में तोड़ने के लिए
  • [::-1] सूची के विपरीत पाने के लिए भाग को केवल स्लाइस सिंटैक्स में विस्तारित किया गया है
  • अंत में हम सब कुछ एक साथ एक स्ट्रिंग में वापस जोड़ते हैं " ".join()और प्रिंट आउट लेते हैं

लेकिन जो लोग बड़े अजगर प्रशंसक नहीं हैं, हम AWKअनिवार्य रूप से एक ही काम करने के लिए उपयोग कर सकते हैं : विभाजन, और रिवर्स में प्रिंट सरणी:

 echo "$VAR" | awk '{split($0,a);x=length(a);while(x>-1){printf "%s ",a[x];x--};print ""}'
100 90 80 70 60 50 40 30 20 10 

1
या कुछ हद तक क्लीनरpython3 -c 'import sys;print(*reversed(sys.argv[1:]))' $VAR
इरुवर

@iruvar, क्लीनर नहीं , जो शेल के विभाजन + ग्लोब ऑपरेटर को सुनिश्चित करेगा बिना यह सुनिश्चित किए कि $IFSइसमें उचित वर्ण हैं और ग्लोब भाग को अक्षम किए बिना।
स्टीफन चेजलस 13

@ स्टीफनचेजेलस, सच में पर्याप्त - अजगर का हिस्सा अभी भी क्लीनर (IMHO) है। तो, "$VAR"पैदावार पर वापस जा रहा हैpython3 -c 'import sys;print(*reversed(sys.argv[1].split()))' "$VAR"
irvar

1

zsh:

print -r -- ${(Oa)=VAR}

$=VARपर विभाजित $VARहै $IFS(Oa)परिणामी सूची को रिवर्स एरे ऑर्डर में क्रमबद्ध करता है। print -r --(जैसे ksh), उसी तरह echo -E -( zshविशिष्ट) का एक विश्वसनीय संस्करण हैecho : इसके तर्कों को प्रिंट करता है जैसा कि अंतरिक्ष द्वारा अलग किया जाता है, जिसे न्यूलाइन द्वारा समाप्त किया जाता है।

यदि आप केवल अंतरिक्ष में विभाजन करना चाहते हैं, और जो कुछ भी $IFSशामिल नहीं है (स्थान, टैब, न्यूलाइन, डिफ़ॉल्ट रूप से शून्य), या तो अंतरिक्ष असाइन करें $IFS, या एक स्पष्ट विभाजन का उपयोग करें:

print -r -- ${(Oas: :)VAR}

रिवर्स संख्यात्मक क्रम में सॉर्ट करने के लिए:

$ VAR='50 10 20 90 100 30 60 40 70 80'
$ print -r -- ${(nOn)=VAR}
100 90 80 70 60 50 40 30 20 10

POSIXly (तो यह भी काम करेगा bash):

शेल बिलिन ( printfकुछ गोले को छोड़कर ) तंत्र के साथ (केवल थोड़े मूल्य वाले चरों के लिए बेहतर)

unset -v IFS # restore IFS to its default value of spc, tab, nl
set -o noglob # disable glob
set -- $VAR # use the split+glob operator to assign the words to $1, $2...

reversed_VAR= sep=
for i do
  reversed_VAR=$i$sep$reversed_VAR
  sep=' '
done
printf '%s\n' "$reversed_VAR"

साथ awk(बड़े चर, विशेष रूप से साथ के लिए बेहतर bashहै, लेकिन (या एक ही तर्क का) बहस के आकार की सीमा तक):

 awk '
   BEGIN {
     n = split(ARGV[1], a);
     while (n) {printf "%s", sep a[n--]; sep = " "}
     print ""
   }' "$VAR"

0

अयोग्य POSIX सॉफ्टवेयर उपकरण एक-लाइनर:

echo `echo $VAR | tr ' ' '\n' | sort -nr`
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.