简体   繁体   中英

Reverse columns in using sed

If i have a file like this:

aa:bb:cc  
dd:ee:ff

I want to reverse the columns to this:

cc bb aa  
ff ee dd

Basically reversing the columns and replacing the ":" with a " "

Ive been just trying to get the reversing down before worrying about the ":" replacement. Im trying to use only sed for this.

sed -r 's/(:.*)(.*:)/\2\1/'

Ideally this should match everything up to the first ":" then match everything after the last ":" then print them in reverse order but thats not the case.

Any help would be nice, i feel like im close but just missing something here.

If you insist using sed:

sed -r ':a;/[^:]*:[^:]*:/{s/([^:]*):([^:]*):(.*)/\2 \1:\3/;ba};/[^:]*:[^:]*$/s/([^:]*):([^:]*)$/\2 \1/;' file

little loop there.

But use awk is better:

awk -F: '{for(i=NF;i>1;i--)printf("%s ",$i);print $1}' file

printf won't return(plus \\n), print would.

awk really is the better tool for this, but if you are restricting yourself to 3 columns, a reasonable way to use sed is:

$ k='\([^:]*\)'
$ sed "s/$k:$k:$k/\3 \2 \1/" input

This might work for you (GNU sed):

sed -r 's/$/:\n/;ta;:a;s/^([^ :]+)\s*:(.*\n)/\2 \1/;ta;s/\n //' file

This appends a newline and another delimiter ( : ) to the end of the line. Then moves the first column to just after the newline and prepends a new delimiter ( ) to it. This is repeated until the first character of the line is a newline which is then removed along with the unwanted extra new delimiter.

NB The ta command following the first substitution is there to reset the truth flag because the first substitution will always succeed.

You wrote: this should match everything up to the first ":" then match everything after the last ":" then print them in reverse order. I think you want aa:bb:cc:dd converted into dd bb cc aa . This can be done with

sed -e "s/^\([^:]*\):\(.*\):\([^:]*\)$/\3 \2 \1/" -e 's/:/ /g' inputfile
# Test
echo "aa:bb:cc
aa:bb:cc:dd" | sed -e "s/^\([^:]*\):\(.*\):\([^:]*\)$/\3 \2 \1/" -e 's/:/ /g'
# Output
cc bb aa
dd bb cc aa

Explanation: ^ matches start of line, $ end-of line. [^:]* matches a string without a : . \\(some_match\\) remembers some_match , which can be shown with \\1 (1 is the first thing in memory).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM