MosesA
MosesA

Reputation: 965

sed - exchange words with delimiter

I'm trying swap words around with sed, not replace because that's what I keep finding on Google search.

I don't know if it's the regex that I'm getting wrong. I did a search for everything before a char and everything after a char, so that's how I got the regex.

echo xxx,aaa | sed -r 's/[^,]*/[^,]*$/'

or

echo xxx/aaa | sed -r 's/[^\/]*/[^\/]*$/'

I am getting this output:

[^,]*$,aaa

or this:

[^,/]*$/aaa

What am I doing wrong?

Upvotes: 0

Views: 228

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 754060

For the first sample, you should use:

echo xxx,aaa | sed 's/\([^,]*\),\([^,]*\)/\2,\1/'

For the second sample, simply use a character other than slash as the delimiter:

echo xxx/aaa | sed 's%\([^/]*\)/\([^/]*\)%\2/\1%'

You can also use \{1,\} to formally require one or more:

echo xxx,aaa | sed 's/\([^,]\{1,\}\),\([^,]\{1,\}\)/\2,\1/'
echo xxx/aaa | sed 's%\([^/]\{1,\}\)/\([^/]\{1,\}\)%\2/\1%'

This uses the most portable sed notation; it should work anywhere. With modern versions that support extended regular expressions (-r with GNU sed, -E with Mac OS X or BSD sed), you can lose some of the backslashes and use + in place of * which is more precisely what you're after (and parallels \{1,\} much more succinctly):

echo xxx,aaa | sed -E 's/([^,]+),([^,]+)/\2,\1/'
echo xxx/aaa | sed -E 's%([^/]+)/([^/]+)%\2/\1%'

Upvotes: 2

hek2mgl
hek2mgl

Reputation: 158030

With sed it would be:

sed 's#\([[:alpha:]]\+\)/\([[:alpha:]]\+\)#\2,\1#' <<< 'xxx/aaa'

which is simpler to read if you use extended posix regexes with -r:

sed -r 's#([[:alpha:]]+)/([[:alpha:]]+)#\2/\1#' <<< 'xxx/aaa'

I'm using two sub patterns ([[:alpha:]]+) which can contain one or more letters and are separated by a /. In the replacement part I reassemble them in reverse order \2/\1. Please also note that I'm using # instead of / as the delimiter for the s command since / is already the field delimiter in the input data. This saves us to escape the / in the regex.

Btw, you can also use awk for that, which is pretty easy to read:

awk -F'/' '{print $2,$1}' OFS='/' <<< 'xxx/aaa'

Upvotes: 1

Related Questions