एक स्ट्रिंग में डॉट-सीमांकित तत्वों का रिवर्स ऑर्डर


14

मेरे पास इनपुट स्ट्रिंग है जैसे:

arg1.arg2.arg3.arg4.arg5

मुझे जो आउटपुट चाहिए वह है:

arg5.arg4.arg3.arg2.arg1

यह हमेशा 5 arg का नहीं है, 2 से 10 हो सकता है।

मैं इसे बाश स्क्रिप्ट में कैसे कर सकता हूं?

जवाबों:


22
  • के संयोजन का उपयोग करना tr+ tac+paste

    $ tr '.' $'\n' <<< 'arg1.arg2.arg3.arg4.arg5' | tac | paste -s -d '.'
    arg5.arg4.arg3.arg2.arg1
  • यदि आप अभी भी बैश पसंद करते हैं, तो आप इस तरह से कर सकते हैं,

    IFS=. read -ra line <<< "arg1.arg2.arg3.arg4."
    let x=${#line[@]}-1; 
    while [ "$x" -ge 0 ]; do 
          echo -n "${line[$x]}."; 
          let x--; 
    done
  • का उपयोग कर perl,

    $ echo 'arg1.arg2.arg3.arg4.arg5' | perl -lne 'print join ".", reverse split/\./;'
    arg5.arg4.arg3.arg2.arg1

2
बाह, मैं सिर्फ पर्ल समाधान पोस्ट करने जा रहा था :)
ilkachachu

10

यदि आप थोड़ा सा बुरा नहीं मानते हैं python:

".".join(s.split(".")[::-1])

उदाहरण:

$ python3 -c 's="arg1.arg2.arg3.arg4.arg5"; print(".".join(s.split(".")[::-1]))'
arg5.arg4.arg3.arg2.arg1
  • s.split(".").अलग-अलग सब्सट्रिंग्स वाली सूची बनाता है, सूची को [::-1]उलटता है और ".".join()उलट सूची के घटकों के साथ जुड़ता है .

5

आप इसे एकल sedआह्वान के साथ कर सकते हैं :

sed -E 'H;g;:t;s/(.*)(\n)(.*)(\.)(.*)/\1\4\5\2\3/;tt;s/\.(.*)\n/\1./'

यह पैटर्न स्पेस में एक प्रमुख न्यूलाइन प्राप्त करने के लिए होल्ड बफर का उपयोग करता है और इसे तब तक क्रमपरिवर्तन करने के लिए उपयोग करता है जब तक कि नईलाइन का किसी भी डॉट द्वारा अनुसरण नहीं किया जाता है, जिस बिंदु पर यह पैटर्न स्पेस से प्रमुख डॉट को हटा देता है और न्यूलाइन को डॉट के साथ बदल देता है।
BRE और थोड़े अलग रेगेक्स के साथ:

sed 'H
g
:t
s/\(.*\)\(\n\)\(.*\)\(\.\)\(.*\)/\1\4\5\2\3/
tt
s/\(\.\)\(.*\)\n/\2\1/'

यदि इनपुट में एक से अधिक लाइन हैं और आप प्रत्येक लाइन पर ऑर्डर को उलटना चाहते हैं:

sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/'

3

SED समाधान:

sed 's/\./\n/g' yourFile | tac | sed ':a; $!{N;ba};s/\n/./g'

3

के साथ zsh:

$ string=arg1.arg2.arg3.arg4.arg5
$ printf '%s\n' ${(j:.:)${(Oas:.:)string}}
arg5.arg4.arg3.arg2.arg1

खाली तत्वों को संरक्षित करने के लिए:

$ string=arg1.arg2.arg3.arg4..arg5.
$ printf '%s\n' ${(j:.:)"${(@Oas:.:)string}"}
.arg5..arg4.arg3.arg2.arg1
  • s:.:: पर विभाजित .
  • Oa: रिवर्स में तरह सरणी एक rray indice rder
  • j:.:: पर शामिल हों .
  • @: "$@"जब डबल कोट्स में ऐसा ही विस्तार होता है, तो विस्तार खाली-खाली नहीं होता है।

POSIX (या bash) समतुल्य कुछ इस तरह हो सकता है:

string=arg1.arg2.arg3.arg4..arg5.

IFS=.; set -f
set -- $string$IFS # split string into "$@" array
unset pass
for i do # reverse "$@" array
  set -- "$i" ${pass+"$@"}
  pass=1
done
printf '%s\n' "$*" # "$*" to join the array elements with the first
                   # character of $IFS

(ध्यान दें कि zsh( shअनुकरण में), yashऔर कुछ- pdkshगोले के गोले उस संबंध में POSIX नहीं हैं कि वे $IFSक्षेत्र परिसीमनकर्ता के बजाय क्षेत्र विभाजक के रूप में व्यवहार करते हैं )

जहां यह यहां दिए गए कुछ अन्य समाधानों से भिन्न है, यह है कि यह न्यूलाइन कैरेक्टर (और zsh, एनयूएल एक या तो) विशेष रूप से व्यवहार नहीं करता है , जिसे $'ab.cd\nef.gh'उलटा किया जाएगा $'gh.cd\nef.ab', $'cd.ab\ngh.ef'या नहीं $'gh.ef.cd.ab'


क्या गलत है IFS="."; set -f; set -- $string$IFS; for i; do rev="$i$IFS$rev"; done; printf '%s\n' "${rev%$IFS}"?

@BinaryZebra कुछ भी नहीं (इसके अलावा शायद for i; doजो POSIX नहीं है (अभी तक) भले ही यह सभी POSIX गोले जो मुझे पता है) द्वारा समर्थित है। यह सिर्फ इतना है कि समाधान एक का सीधा अनुवाद है zsh(सरणी में विभाजित करें, रिवर्स सरणी, सरणी तत्वों में शामिल हों) लेकिन पोसिक्स-ओनली ऑपरेटर्स का उपयोग करना। (मुझे लगता है कि गोले, धन्यवाद के पार लगातार काम करने के string=$string$IFS; set -- $stringलिए बदल गया है set -- $string$IFS)।
स्टीफन चेजलस

2

मैं देख रहा हूं कि राहुल ने पहले से ही एक देशी बैश समाधान (दूसरों के बीच) पोस्ट किया है, जो मेरे साथ आए पहले संस्करण का एक छोटा संस्करण है:

function reversedots1() (
  IFS=. read -a array <<<"$1"
  new=${array[-1]}
  for((i=${#array[*]} - 2; i >= 0; i--))
  do
    new=${new}.${array[i]}
  done
  printf '%s\n' "$new"
)

लेकिन मैं वहाँ नहीं रुक सका, और एक पुनरावर्ती बाश केंद्रित समाधान लिखने की आवश्यकता महसूस की:

function reversedots2() {
  if [[ $1 =~ ^([^.]*)\.(.*)$ ]]
  then
    printf %s $(reversedots2 "${BASH_REMATCH[2]}") . "${BASH_REMATCH[1]}"
  else
    printf %s "$1"
  fi
}

2

एक awkजवाब नहीं देखा , तो यहाँ एक है:

 echo 'arg1.arg2.arg3' | awk -F. '{for (i=NF; i>0; --i) printf "%s%s", (i<NF ? "." : ""), $i; printf "\n"}'

1

शुद्ध बैश, इनपुट पर अनुगामी अवधि की आवश्यकता है:

echo 'foo.bar.baz.' | ( while read -d . f;do g="$f${g+.}$g" ;done;echo "$g" )

printf %s "$g"यदि कोई भी बिंदीदार तत्व हाइफ़न के साथ शुरू हो सकता है, तो उपयोग करें ।

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