开发者

How to sort characters in a string?

开发者 https://www.devze.com 2022-12-22 06:34 出处:网络
I would like to sort the characters in a string. E.g. echo cba | sort-command abc Is there a command that wi开发者_如何学Pythonll allow me to do this or will I have to write an awk script to itera

I would like to sort the characters in a string.

E.g.

echo cba | sort-command
abc

Is there a command that wi开发者_如何学Pythonll allow me to do this or will I have to write an awk script to iterate over the string and sort it?


echo cba | grep -o . | sort |tr -d "\n"


Please find the following useful methods:

Shell

Sort string based on its characters:

echo cba | grep -o . | sort | tr -d "\n"

String separated by spaces:

echo 'dd aa cc bb' | tr " " "\n" | sort | tr "\n" " "

Perl

print (join "", sort split //,$_)

Ruby

ruby -e 'puts "dd aa cc bb".split(/\s+/).sort' 

Bash

With bash you have to enumerate each character from a string, in general something like:

str="dd aa cc bb";
for (( i = 0; i < ${#str[@]}; i++ )); do echo "${str[$i]}"; done

For sorting array, please check: How to sort an array in bash?


This is cheating (because it uses Perl), but works. :-P

echo cba | perl -pe 'chomp; $_ = join "", sort split //'


Another perl one-liner

$ echo cba | perl -F -lane 'print sort @F'
abc

$ # for reverse order
$ echo xyz | perl -F -lane 'print reverse sort @F'
zyx
$ # or
$ echo xyz | perl -F -lane 'print sort {$b cmp $a} @F'
zyx
  • This will add newline to output as well, courtesy -l option
    • See Command switches for doc on all the options
  • The input is basically split character wise and saved in @F array
  • Then sorted @F is printed


This will also work line wise for given input file

$ cat ip.txt 
idea
cold
spare
umbrella

$ perl -F -lane 'print sort @F' ip.txt 
adei
cdlo
aeprs
abellmru


This would have been more appropriate as a comment to one of the grep -o . solutions (my reputation's not quite up to that low bar alas, damn my lurking), but I thought it worth mentioning that separating letters can be done more efficiently within the shell. It's always worth avoiding code, but this letsep function is pretty small:

letsep ()
{
INWORD="$1"
while [ "$INWORD" ]
do
    echo ${INWORD:0:1}
    INWORD=${INWORD#?}
done
}

. . . and outputs one letter per line for an input string of arbitrary length. For example, once letsep is defined, populating an array FLETRS with the letters of a string contained in variable FRED could be done (assuming contemporary bash) as:

readarray -t FLETRS < <(letsep $FRED)

. . . which for word-size strings runs about twice as fast as the equivalent :

readarray -t FLETRS < <(echo $FRED | grep -o .)

Whether this is worth setting up depends on the application. I've only measured this crudely, but the slower procedural code seems to maintain an advantage over the context switch up to ~60 chars (grep is obviously more efficient, but loading it is relatively expensive). If the above operation is taking place in one or more steps of a loop over an indeterminate number of executions, the difference in efficiency can add up (at which point some might argue for switching tools and rewriting regardless, but that's another set of tradeoffs).

0

精彩评论

暂无评论...
验证码 换一张
取 消