Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I know that I can reverse any sentence: echo "a,b,c,d" | rev

but what if I want to reverse only the first part of a sentence, I have tried this:

echo "a,b,c,d Access" | rev

and I get this:

sseccA d,c,b,a, and what I really want is:

d,c,b,a Access

How can I do this?

share|improve this question
There are a lot of useful answers that will help you in this question: unix.stackexchange.com/questions/132779/… – Networker Aug 3 '14 at 19:44
@Networker, Thanks but the answers add a string ".in-addr.arpa" at the end, here I'm already have the string "Access" – user79550 Aug 3 '14 at 19:47
So the problem is: given $1 $2 $3...$n, print (rev $1) $2 $3...$n? – Mikel Aug 3 '14 at 20:06
@Mikel, yes this is it – user79550 Aug 3 '14 at 20:09
up vote 7 down vote accepted

One way is to use read to break the line into the first word and the rest, then call rev on only the first word

$ echo "a,b,c,d Access" | { read -r first rest; printf '%s %s\n' "$(rev <<< "$first")" "$rest"; }
d,c,b,a Access
share|improve this answer
That assumes the input doesn't contain backslash characters and $first doesn't start with -. – Stéphane Chazelas Aug 3 '14 at 20:14
Yeah, we can use read -r and printf '%s if necessary. – Mikel Aug 3 '14 at 20:17
Then why don't we? Why promote a broken command like echo? – Stéphane Chazelas Aug 3 '14 at 20:18
Done, but untested (not at my computer). – Mikel Aug 3 '14 at 20:21

With sed:

sed 's/^/ /;:1
     s/^\([^ ]*\) \([^ ]\)/\2\1 /;t1
     s/ //'

With perl:

perl -pe 's/\S+/reverse $&/e'

With zsh:

string='a,b,c,d Access'
setopt extendedglob
result=${string/(#m)[^ ]#/${(j::)${(Oas::)MATCH}}}
share|improve this answer

Using pee (pipe tee) from moreutils (apt-get install moreutils):

echo -n "a,b,c,d Access" | pee "cut -d ' ' -f 1 | rev" "cut -d ' ' -f 2" | tr '\n' ' '

The result is d,c,b,a Access with a trailing space, which comes from a translated newline.

share|improve this answer
bash: pee: command not found – user79550 Aug 3 '14 at 20:05
Try apt-get install moreutils on Debian/Ubuntu or the equivalent on your Linux. – Volker Siegel Aug 3 '14 at 20:06
I have install pee and have tried the command but it failed: a,b,c,d Access – user79550 Aug 3 '14 at 20:10
@user79550 Hmm... It works for me - but I had left out the rev in the first version I saved, edited shortly after. Can you check the rev is there? – Volker Siegel Aug 3 '14 at 20:12
Upvoted because it works for the original question, but take note that it doesn't work for multiple fields (words). – Cristian Ciupitu Aug 3 '14 at 20:31

Depending on Neven answer:

You can do this using this shell script:

secondPart=`echo "a,b,c,d Access" | awk '{print $2} '`
firstPart=`echo "a,b,c,d Access" | awk '{print $1} '| awk -F , '{print $4","$3","$2","$1""}'`
echo "$firstPart $secondPart"

in command line just type:

sh yourShellscript.sh

or using one command line as Jidder suggeted:

awk '$1=gensub(/(.),(.),(.),(.)/,"\\4,\\3,\\2,\\1","g",$1)' <<< "a,b,c,d Access"
share|improve this answer
Thanks but can I do it using one command line – user79550 Aug 3 '14 at 20:05
@user79550 awk awk '$1=gensub(/(.),(.),(.),(.)/,"\\4,\\3,\\2,\\1","g",$1)' <<< "a,b,c,d Access" – user78605 Aug 4 '14 at 10:09
@Jidder, Thanks Updated – Networker Aug 4 '14 at 11:18

A perl solution:

$ echo "a,b,c,d Access" | perl -anle 'print ~~reverse($F[0])," @F[1..$#F]"'
d,c,b,a Access
share|improve this answer

Fair warning: this relies on your commas.

echo "a,b,c,d Access" | tr ,\  '[\n*]' | 
sed '1!G;$s/\n/,/g;s/\([^,]*\),\(.*\)/\2 \1/p;h;d'


d,c,b,a Access

It's kinda long - longer than it needs to be. It's easier this way:

set -f ; IFS=,\                                                                 
set -- ${0+a,b,c,d Access}
while [ -n "${2+?}" ]
do  r="$1,$r" 
shift ; done    
echo "${r%,} $1"


d,c,b,a Access

Still kinda long, but at least it makes sense. It get's a little easier with a function because you get a shell array. Like:

rev() ( i=
    set -f ; IFS=$1 ; shift ; set -- $*
    until [ "$((i=${i:=($#+1)}-1))" -eq 0 ]
    do  [ "$i" -gt 1 ] && s=$IFS || s=                                          
        eval printf '"%s$s"' \""\$$i"\"
rev , a,b,c,d && echo \ Access


d,c,b,a Access

Or if you have it in a variable:

var="a,b,c,d Access"
rev , "${var% *}" && echo " ${var##* }"


d,c,b,a Access
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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