LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Replacing character position within the string of a file (https://www.linuxquestions.org/questions/linux-newbie-8/replacing-character-position-within-the-string-of-a-file-682011/)

scroy 11-08-2008 02:51 PM

Replacing character position within the string of a file
 
Hi,
I am trying to read a file that has a double value followed by minus sign (Such as 9999999.99-). I want to take this minus from end of the number to beginning of the number (such as -9999999.99).

Could you please help me how can achieve this?
File is delimited by coma and format has provided below -

asdfasdf,7887687.88-,aasdfas
213412.78-,5345645.00,shdfjghh
dsafsdf,asdfafdf,23452345.78-


Thanks a lot.

druuna 11-08-2008 03:33 PM

Hi,

Would this help:

sed 's/\([0-9][0-9]*\.[0-9][0-9]\)-/-\1/' infile

Sample run on given example:
Quote:

$ sed 's/\([0-9][0-9]*\.[0-9][0-9]\)-/-\1/' infile
asdfasdf,-7887687.88,aasdfas
-213412.78,5345645.00,shdfjghh
dsafsdf,asdfafdf,-23452345.78
Sed looks for a string of numbers ([0-9][0-9]*), followed by a dot (\.), followed by 2 numbers ([0-9][0-9] and a dash (-).
Part of the search string (the number part) is between \( and \), all that is found can be represented as \1 in the replace string. This is called back referencing.

Hope this helps.

scroy 11-08-2008 04:22 PM

Quote:

Originally Posted by druuna (Post 3335584)
Hi,

Would this help:

sed 's/\([0-9][0-9]*\.[0-9][0-9]\)-/-\1/' infile

Sample run on given example:

Sed looks for a string of numbers ([0-9][0-9]*), followed by a dot (\.), followed by 2 numbers ([0-9][0-9] and a dash (-).
Part of the search string (the number part) is between \( and \), all that is found can be represented as \1 in the replace string. This is called back referencing.

Hope this helps.

Hi,
Thanks for the quick respnose but it is not working for me.
I am using korn shell. does it matter?
Here is the output -

sed 's/\([0-9][0-9]*\.[0-9][0-9]\)-/-\1/' test
asdfas,98789789.90,-7868876.90
-1234.88,asdfas,123412341.66
asdfasd,-2452345.45.23452345.90
-34523.88,3245.77,23452345-

Please advice.
Thanks

jschiwal 11-08-2008 04:39 PM

Code:

sed -r 's/([[:digit:]]+\.[[:digit:]][[:digit:]])-/-\1/g' junk
asdfasdf,-7887687.88,aasdfas
-213412.78,5345645.00,shdfjghh
dsafsdf,asdfafdf,-23452345.78

If an input sample you are using (that doesn't work) is different than what you gave us in the first message, please post it.
I did try this version will an entry that had two numbers followed by a minus sign. My input set and sed
command assumes that there are two digits after the decimal point.
Code:


cat junk
asdfasdf,7887687.88-,aasdfas
213412.78-,5345645.00,shdfjghh
dsafsdf,asdfafdf,23452345.78-
213412.78-,5345645.20-,shdfjghh
dsafsdf,asdfafdf,23452345.78-

~> sed -r 's/([[:digit:]]+\.[[:digit:]][[:digit:]])-/-\1/g' junk
asdfasdf,-7887687.88,aasdfas
-213412.78,5345645.00,shdfjghh
dsafsdf,asdfafdf,-23452345.78
-213412.78,-5345645.20,shdfjghh
dsafsdf,asdfafdf,-23452345.78

I used the -r option for extended regular expressions. I got lazy and didn't want to type [[:digit:]][[:digit:]]* instead of [[:digit:]]+. The "[[:digit:]]" is a character class equivalent to using "[0-9]".
The only real difference between the two sed commands is that I added "g" at the end to handle the case of more
than one number being changed on a single line. We both assumed two digits after the decimal point.

You could use this version is the decimal point is optional. It still assumes two digits after the decimal point.
You can use [[:digit:]]{1,} or something similar instead.
Code:

sed -r 's/([[:digit:]]+)(\.[[:digit:]][[:digit:]])?-/-\1\2/g' junk

Another possible solution is to change your locale setting so that your data set doesn't print numbers that way (if you are producing them yourself).

druuna 11-08-2008 04:41 PM

Hi,

You don't show what your input file looks like, but the output does look correct.

Maybe you think the last number on the last line is wrong, but it isn't (theres no dot followed by 2 numbers).

pixellany 11-08-2008 04:43 PM

I did a cut and paste from your results and got the same (right answer) as Druna. (I'm on BASH)

The results that you are getting suggest that the ranges (eg [0-9]) are not being interpreted correctly. You might want to try sed -r (the -r flag turns on extended regular expressions.)

Also, try experiments with simpler expressions, eg: sed 's/[0-9]/XXX/' filename (This should replace only the first occurence of any numeral.)

Note that you probably want the g flag unless you know that you will only have one match per line. eg: sed 's/[0-9]/XXX/g' filename (replaces ALL occurences of a numeral.)

Why this would be different in the KORN shell is way above my pay grade...

druuna 11-08-2008 04:47 PM

Hi,

pixellany is completely correct about adding the g if multiple numbers (with dots and 2 numbers) are on one line.

scroy 11-08-2008 04:54 PM

Hi,
I am getting the following error message.
Thanks

sed: Not a recognized flag: r
Usage: sed [-n] Script [File ...]
sed [-n] [-e Script] ... [-f Script_file] ... [File ...]

druuna 11-08-2008 04:59 PM

Hi,

Without knowing what you are doing we cannot help you :)
Please post the command(s) you tried, the inputfile you use and the output (if any).

scroy 11-08-2008 05:11 PM

Hi Here is all information.
Thanks

Here is the content of my file called test:
asdfas,98789789.90,7868876.90-
1234.88-,asdfas,123412341.66
asdfasd,2452345.45-.23452345.90
34523.88-,3245.77,23452345-



And this is the command I did use:
sed -r 's/([[:digit:]]+\.[[:digit:]][[:digit:]])-/-\1/g' test


And this is the error message I got:
sed: Not a recognized flag: r
Usage: sed [-n] Script [File ...]
sed [-n] [-e Script] ... [-f Script_file] ... [File ...]

druuna 11-08-2008 05:20 PM

Hi,

The -r flag is not needed.

Both jschiwal's and my solution (with the g included) give the correct output:
Quote:

$ cat infile
asdfas,98789789.90,7868876.90-
1234.88-,asdfas,123412341.66
asdfasd,2452345.45-.23452345.90
34523.88-,3245.77,23452345-

$ sed 's/\([0-9][0-9]*\.[0-9][0-9]\)-/-\1/g' infile
asdfas,98789789.90,-7868876.90
-1234.88,asdfas,123412341.66
asdfasd,-2452345.45.23452345.90
-34523.88,3245.77,23452345-

$ sed -r 's/([[:digit:]]+\.[[:digit:]][[:digit:]])-/-\1/g' infile
asdfas,98789789.90,-7868876.90
-1234.88,asdfas,123412341.66
asdfasd,-2452345.45.23452345.90
-34523.88,3245.77,23452345-
What output did you expect?

scroy 11-08-2008 05:31 PM

Hi,
Thanks a lot. It is working now.
What I need to do if I want ignore the decimal restriction?
I mean, I want to make changes on the number that does not have decimal.
Such as the last number in last row.
Thanks

druuna 11-08-2008 05:43 PM

Hi,

Is this better: sed 's/\([0-9][0-9\.]*[0-9]\)-/-\1/g' infile?

Example run:
Quote:

$ cat infile
asdfas,98789789.90,7868876.90-
1234.88-,asdfas,123412341.66
asdfasd,2452345.45-.23452345.90
34523.88-,3245.77,23452345-

$ sed 's/\([0-9][0-9\.]*[0-9]\)-/-\1/g' infile
asdfas,98789789.90,-7868876.90
-1234.88,asdfas,123412341.66
asdfasd,-2452345.45.23452345.90
-34523.88,3245.77,-23452345

scroy 11-08-2008 05:45 PM

Quote:

Originally Posted by druuna (Post 3335670)
Hi,

Is this better: sed 's/\([0-9][0-9\.]*[0-9]\)-/-\1/g' infile?

Example run:

This is perfect.
Thanks a lot.


All times are GMT -5. The time now is 08:11 PM.