Reputation: 21
I have simple input like this :
11111(n)
222222(p)
33333333(:)
I can use sed backreference to swap parenthesis with digits like this :
sed -e 's/\([[:digit:]]*\)\((.*)\)/\2 \1/' file
which produce
(n) 11111
(p) 222222
(:) 33333333
It's cool !
But things became more difficult with potential decimal digits, like this
11111(n)
11111.111(n)
2222222.22(p)
33.3333333(:)
I've try many commands, like
sed -e 's/\([[:digit:]]*(\.[[:digit:]]*?)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*\.?[[:digit:]]*?)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*\.*[[:digit:]]*)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*.*[[:digit:]]*)\)\((.*)\)/\2 \1/' file
Output desired :
(n) 11111
(n) 11111.111
(p) 2222222.22
(:) 33.3333333
Note that digits can be arbitrary long (1 to n digits), and decimal mark (.) and decimal digits are optional.
Furthermore, sed
don't seem to have \d
shorthand, as pointed in stackexchange
Upvotes: 1
Views: 859
Reputation: 5252
Why not just use simple collection?
sed -e 's/\([0-9.]*\)\((.*)\)/\2 \1/' file
Since [0-9] and [:digit:] are basically the same, but when you want include other character, former one is more intuitive.
Given a second thought, in which I see that you were trying to match the legitimate number, i.e. no point or only one point, thus improved sed one would be:
sed -r 's/([0-9]+(\.[0-9]+)?)(\(.*\))/\3 \1/' file
-r to support +? in RE and switch parentheses' escape around.
Or use perl to avoid all those RE extension confusion:
perl -lne 'print "$3 $1" if /(\d+(\.\d+)?)\s*(\(.*?\))/' file
Update: As Benjamin W. mentioned in comments, [0-9] and [[:digit:]] are not the same, so if you want to consider possible digits in other languages, the sed one should be:
sed -r 's/([[:digit:]]+(\.[[:digit:]]+)?)(\(.*\))/\3 \1/' file
Upvotes: 0
Reputation: 85530
It gets quite simple when you know what to match in the POSIX bracket expression with [:digit:]
. All you need to do is include another .
so that the bracket expression would mean set of digits along with .
,
sed 's/\([[:digit:].]*\)\((.*)\)/\2 \1/' file
Also you don't need to mention -e
, because sed
by default operates in BRE (Basic Regular Expressions) mode and with -E
the ERE (Extended Regular Expression) mode is enabled. Also \d
is not a valid regular expression construct used by any versions of sed
(POSIX, GNU or FreeBSD) to match digits. I suppose it is supported in the PCRE library in which you could use perl
perl -lne 'print "$2 $1" if /(\d+\.?\d*).*(\([^)]*\))/' file
Upvotes: 2
Reputation: 784898
You may use this sed
:
sed -E 's/^([.[:digit:]]+)(\([^)]*\))/\2 \1/g' file
(n) 11111
(n) 11111.111
(p) 2222222.22
(:) 33.3333333
Here [.[:digit:]]+
will match 1+ of any digit or dot character.
Upvotes: 1