I was looking at this question and I wondered if the following could be done from terminal. I did it in python, just want to see if it could be done from terminal, bash scripting or whatever.

Suppose I have a file that looks like so:


could it be sorted like so, by rows (lines)


or is it too complicated? I did it using python, I just want to know if it could be done so next time I might not use python. What I have done, is creating lists and sorting them.

  • I asked it here because I saw the other question, if it should not be asked here feel free to close it or delete it – Lynob Apr 13 '14 at 23:08
  • 5
    I added the missing comma between 5 and 14 in your input example. Based on your output, I assume that was a typo, please clarify if it was not. – terdon Apr 14 '14 at 4:51

Here's another Perl approach:

perl -F, -lane 'print join ",",sort {$a<=>$b} @F' file.txt

And another shell/coreutils one (though personally, I prefer steeldriver's excellent answer which uses the same idea):

while read line; do 
    tr , $'\n' < <(printf -- "%s" "$line") | sort -g | tr $'\n' , | sed 's/,$/\n/';
done < file.txt
  • 1
    Nice solution, I up-vote immediately – Sylvain Pineau Apr 14 '14 at 5:41
  • As is yours and as did I :) – terdon Apr 14 '14 at 5:45
  • I hate it when I receive too many good answers :) and when you have to pick one randomly, it's like asking myself "what do I like more, chocolate bars or icecream?" – Lynob Apr 14 '14 at 21:28

This should do about what you're looking for. It will read a file (test.txt) and create an output file (sorted.txt) with the sorted lines in the same order as they appear in the original file.

while read line; do j=$(echo "$line" | sed -e 's/,/\n/g' | sort -n); echo "$j" 
    | sed -e 's/ /,/g' >> sorted.txt; done < test.txt
  • did you note the space in the first line 2,4,5 14,9? – Avinash Raj Apr 14 '14 at 4:36
  • bad usage of cat! To operate on each line, do while read line; do ...; done < test.txt – Fredrik Pihl Apr 14 '14 at 7:30
  • @FredrikPhil: Thank you. I have edited my answer. – jkt123 Apr 14 '14 at 9:11

The only real difficulty in doing what you want using command-line scripting is that the available sort function expects to sort lines within a file, rather than fields within a line. To work around that, you could replace the field delimiters, line-by-line, with newlines prior to the sort function, then replace the newlines with delimiters again in each line after sorting.

There are a number of available text processing utilities which would allow you to do that (including sed, awk, or even the simple tr) however the bash shell itself can do a lot nowadays. Assuming you meant for the input to be comma-delimited (you have a mix of commas and whitespace delimiters in your example) you could do:

while read line; do 
  sorted=$(sort -g -- <<< "${line//,/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

If you do need to handle space delimiters in the input, then you can add them as part of a character list [, ] for the input substring replacement:

while read line; do 
  sorted=$(sort -g -- <<< "${line//[, ]/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

(note that the output remains strictly comma-delimited though).


Here comes an awk solution,

while read -r line; do (echo $line | awk '{ n=split($1,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}') | xargs | sed -e 's/ /,/g'; done < text.txt


  • awk '{ n=split($1,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}'

    awk Splits the field 1 according to the delimiter , and store each value into the array a finally the top position is stored into the variable n. Next asort(a) function sort down the array values.Then the for loop inside the awk command prints the sorted values in the format of record by record.

  • xargs | sed -e 's/ /,/g'

    xargs combines all the rows into a single row.

  • sed -e 's/ /,/g'

    It replaces the spaces with commas ,

  • while read -r line;

    All the above awk,xargs,sed functions are done line by line with the help of while loop.


python -c "your code here" input.txt

Or, if your program has multiple lines and eval() is too slow:

python yourprogram.py input.txt

This oneliner works:

python -c "for l in open('input.txt'):print(','.join(sorted(l.strip().split(','), key=int)))"
  • The OP is not looking for a python-based solution. – jobin Apr 14 '14 at 16:43
  • Yes he is: "just want to see if it could be done from terminal, bash scripting or whatever." – Cees Timmerman Apr 14 '14 at 17:01
  • Lol, you nailed it, then! – jobin Apr 14 '14 at 17:04

Using tr and sed

Similar in spirit to what jkt123 wrote:

while read i; do tr , \\n <<< $i | sort -n | tr \\n , | sed 's/,$//'; done

It iterates over the lines, and for each line replaces commas by newlines, sorts the resulting lines numerically, then turns newlines back to commas. The main problem is that this will end the whole result with a comma not a newline, which is addressed by that last sed. It strips the last comma and also implicitely adds a newline to its output.

Using bash arrays

Here is a different approach to deal with this “join with commas” issue:

while read i; do j=( $(tr , \\n <<< $i | sort -n) ); ( IFS=,; echo "${j[*]}"; ); done

Or written with line wraps:

while read i
   j=( $(tr , \\n <<< $i | sort -n) )
   ( IFS=,; echo "${j[*]}"; )

It uses a bash array to store the result of the sorted row, and makes use of the way bash expands arrays into string literals using the IFS special variable.


You can do this easily using perl

consider you have file text.txt

cat text.txt


Now the following perl code will sort the rows in text.txt

 perl -i -e 'while(<>){chomp; my @sorted = sort { $a <=> $b } split(",", $_); print join (",", @sorted); print "\n"}' text.txt

After sorting

cat text.txt

  • 2
    You could shorten this significantly with perl -i -lne 'print join (",", sort {$a <=> $b} split(",", $_));' text.txt. The -n flag is the same as while(<>){} and the -l adds a \n to every print call and also activates implicit chomp(). – terdon Apr 14 '14 at 6:00

The shortest solution using a perl oneliner:

perl -ne 'print join(",", sort { $a <=> $b } split(/,|\n/))."\n"' text.txt
  • Heh, I'd left my answer open for a while and hadn't seen this, but not the shortest :P – terdon Apr 14 '14 at 5:39
  • 1
    Je m'incline ;-) – Sylvain Pineau Apr 14 '14 at 5:41

I needed this functionality too, and a solution I found is as follows (assuming data are in test file):

cat test | while read line; do echo $(echo $line | datamash -t',' transpose |sort -g| datamash -t',' transpose); done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.