I have to sort all of the words from a file given as parameter in a shell script. Here is the one-liner:
tr [:space:] '\n' <$1 | sort -nrk2,2 | uniq -c |sed 's/^ \+//g'Basically, if I have something like this in my file:
bla bla bla bla hu hu huIt will output
4 bla
3 huI want them to be something like
bla 4
hu 3 1 2 Answers
You could replace your sed command with a simple awk command that swaps the field order
... | awk '{print $2,$1}' 3 There are many, many ways of doing this. Steeldriver already gave you the classic awk approach. Here are some other choices:
Use
sedto capture two groups of non-whitespace (\S) characters and then switch them around:... | sed -E 's/\s*(\S+)\s+(\S+)/\2 \1/'Use
perl. Its-aswitch makes it work likeawk. It will automatically split each input line on whitespace and save each field as an element of the array@F. Therefore, the 1st field will be$F[0], the second$F[1]etc.:... | perl -lane 'print "$F[1] $F[0]"'Use Perl for the whole thing:
perl -lane '$k{$_}++ for @F; }{ print "$_ $k{$_}" for keys(%k)' "$1"Here,
perlreads the input file line by line and applies the script to each line.$k{$_}++ for @Fsaves each word (each field from@F) as a key in the hash%kand increments the associated value by one each time the word is seen. Then, after the file has been processed (that's what the}{means), it will print the word ($_) and the number of times it was seen ($k{$_}) for each key stored in the hash.Use
awkfor the whole thing:awk '{for(i=1;i<=NF;i++){a[$i]++}}END{for(i in a){print i,a[i]}}' "$1"The first
forloop iretares over each field and adds one to the value associated with that field in the arraya. Then, at the end of the file, it loops over each element inaand prints the element (the word) and the associated value (the number of times the word was seen).Use the shell with your original pipeline:
... | while read a b; do echo "$b $a"; done