Update value within a unix flat file - unix

Kindly help. I want to make .0 to be 0.0 within a UNIX file yyyyy.csv :
603905209;47.824;USD
603905477;57.199;USD
603938657;3.2281;USD
603949388;.00191;USD
603937274;.00563;USD
603911160;.00287;USD
I want the result to be
603905209;47.824;USD
603905477;57.199;USD
603938657;3.2281;USD
603949388;0.00191;USD
603937274;0.00563;USD
603911160;0.00287;USD
but I got this result:
603905209;0.4.7824;USD
603905477;0.5.7199;USD
603938657;0.3.2281;USD
603949388;0.00191;USD
603937274;0.00563;USD
603911160;0.00287;USD
Below is my command:
sed 's/;.0/;0.0/g' yyyyy.csv | sed 's/;.2/;0.2/g' | sed 's/;.1/;0.1/g' | sed 's/;.3/;0.3/g' | sed 's/;.4/;0.4/g' | sed 's/;.5/;0.5/g'| sed 's/;.6/;0.6/g' | sed 's/;.7/;0.7/g' | sed 's/;.8/;0.8/g' | sed 's/;.9/;0.9/g' > xxxxx.csv

You need to escape all the dots present in your regex or otherwise it would match any character. That is, . is a special meta character in regex which matches any character. To match a literal dot, you need to escape the ..
sed 's/;\.0/;0.0/g' yyyyy.csv
And this would be enough.
$ sed 's/;\.\([0-9]\)/;0.\1/g' file
603905477;57.199;USD
603938657;3.2281;USD
603949388;0.00191;USD
603937274;0.00563;USD
603911160;0.00287;USD
In basic sed, \(...\) called capturing group, which is used to capture the characters matched by the pattern present inside that group. So the pattern present inside the group is [0-9] which matches a digit from 0-9. We could refer the captured characters through back-referencing ie, \1. \1 at the replacement part refers to the characters which are present inside the group index 1.

Change your command to:
sed 's/;\./;0./g' File
i.e, just substitute ;. with ;0..

Just print your file using a tool that understands numbers:
$ awk -F';' '{printf "%d;%f;%s\n", $1,$2,$3}' file
603905209;47.824000;USD
603905477;57.199000;USD
603938657;3.228100;USD
603949388;0.001910;USD
603937274;0.005630;USD
603911160;0.002870;USD
awk -F';' '{printf "%d;%.5f;%s\n", $1,$2,$3}' file
603905209;47.82400;USD
603905477;57.19900;USD
603938657;3.22810;USD
603949388;0.00191;USD
603937274;0.00563;USD
603911160;0.00287;USD
$ awk -F';' '{printf "%d;%.2f;%s\n", $1,$2,$3}' file
603905209;47.82;USD
603905477;57.20;USD
603938657;3.23;USD
603949388;0.00;USD
603937274;0.01;USD
603911160;0.00;USD
Whatever precision you like...

Related

Surround every line with single quote except empty lines

My goal is to add a single apostrophe to every line in the file and skip empty lines.
file.txt:
Quote1
Quote2
Quote3
So far I have used sed:
sed -e "s/\(.*\)/'\1'/"
Which does the job but creates apostrophes also in empty lines:
'Quote1'
'Quote2'
''
'Quote3'
My goal:
'Quote1'
'Quote2'
'Quote3'
How could I achieve this by using sed, or maybe it should it be awk.
.* means zero or more characters, you want 1 or more characters which in any sed would be ..*:
$ sed "s/..*/'&'/" file
'Quote1'
'Quote2'
'Quote3'
You can also write that regexp as .\+ in GNU sed, .\{1,\} in POSIX seds, and .+ in GNU or OSX/BSD sed when invoked with -E.
The above assumes lines of all blanks should be quoted. If that's wrong then:
$ sed "s/.*[^[:blank:]].*/'&'/" file
'Quote1'
'Quote2'
'Quote3'
In any awk assuming lines of all blanks should be quoted:
$ awk '/./{$0="\047" $0 "\047"}1' file
'Quote1'
'Quote2'
'Quote3'
otherwise:
$ awk 'NF{$0="\047" $0 "\047"}1' file
'Quote1'
'Quote2'
'Quote3'
You can see the difference between the above with this:
$ printf ' \n' | sed "s/..*/'&'/"
' '
$ printf ' \n' | sed "s/.*[^[:blank:]].*/'&'/"
$ printf ' \n' | awk '/./{$0="\047" $0 "\047"}1'
' '
$ printf ' \n' | awk 'NF{$0="\047" $0 "\047"}1'
$
One way:
awk '$1{$0 = q $0 q}1' q="'" file
Add quotes only if 1st column($1) has some value. 1 to print every line.
Assuming you want to add the single quotes to lines that contain nothing but whitespace:
sed -E "/./s/(.*)/'\1'/"
Another sed
sed '/^$/!{s/^/\x27/;s/$/\x27/}' file
The above script says
Look for an empty line - /^$/ - pattern.
For those lines that doesn't follow the above pattern(!), substitute start(^) and end($) with single quotes(\x27).
You can use perl to check for a negative lookbehind, asserting that you won't match an "empty" line:
perl -pe 's/(?<!$)(.*)/"\1"/' file
Another alternative is being more specific in your regex, as #edmorton suggested in his answer.
tried on gnu sed
sed -E "s/\S+/'&'/" file.txt

Sed command garbled on Solaris [duplicate]

I have this data in file.txt:
1234-abca-dgdsf-kds-2;abc dfsfds 2
123-abcdegfs-sdsd;dsfdsf dfd f
12523-cvjbsvndv-dvd-dvdv;dsfdsfpage
I want to replace the string after "-" and up to ";" with just ";", so that I get:
1234;abc dfsfds 2
123;dsfdsf dfd f
12523;dsfdsfpage
I tried with the command:
sed -e "s/-.*;/;" file.txt
But it gives me the following error:
sed command garbled
Why is this happening?
sed replacement commands are defined as (source):
's/REGEXP/REPLACEMENT/[FLAGS]'
(substitute) Match the regular-expression against the content of the pattern space. If found, replace matched string with REPLACEMENT.
However, you are saying:
sed "s/-.*;/;"
That is:
sed "s/REGEXP/REPLACEMENT"
And hence missing a "/" at the end of the expression. Just add it to have:
sed "s/-.*;/;/"
# ^
You are missing a slash at the end of the sed command:
Should be "s/-.*;/;/"
-.* here the * greedy, so this would fail if there are more than one ;
echo "12523-cvjbsvndv-dvd-dvdv;dsfdsfpage;test" | sed -e "s/-.*;/;/"
12523;test
Change to -[^;]*
echo "12523-cvjbsvndv-dvd-dvdv;dsfdsfpage;test" | sed -e "s/-[^;]*;/;/"
12523;dsfdsfpage;test
This should work :
sed 's/-.*;/;/g' file > newFile

Adding string after a specific string using sed Unix

I have a string in a file like this:
"Value1=[random number]"
After this string I want to add another string, specifically:
"Value2=100"
If I try to use:
sed '/Value1=/a Value2=100' myfile.txt
It will fail because I have not included the fact that Value1=[some random number].
How do I add the condition that Value1=random number and Value2 should be added to this string?
sed '/Value1=[0-9]\+/a Value2=100' myfile.txt
The [0-9]\+ will match any string of digits. For example, on my cygwin, GNU sed 4.2.2,
echo Value1=42 | sed '/Value1=[0-9]\+/a Value2=43'
produces
Value1=42
Value2=43
Edit: If the number may or may not be in double-quotes, use:
sed '/Value1="\?[0-9]\+"\?/a Value2=43'
The "\? is an optional double-quote.
Something like this:
$ sed 's,\(Value1=200\),\1 Value2=100,' myfile.txt
Result:
Value1=200 Value2=100
echo '"Value1=400"' | sed 's/"Value1=.*"/&\n"Value2=100"/'
Output:
"Value1=400"
"Value2=100"
Or:
echo '"Value1=400"' | sed 's/"Value1=.*"/& "Value2=100"/'
Output:
"Value1=400" "Value2=100"

How to append suffix to all string matched regular expression in unix

I need to replace all occurrences of string in specific format (in my case colon followed by some number) with same string with suffix in a file, like this:
:123456 -> :123456_suffix
Is there a way to do it with sed or other unix command-line tool?
Sed should do that:
sed -i~ -e 's/:\([0-9]\{1,\}\)/:\1_suffix/g' file
^ ^ ^ ^ ^ ^
| | | | | |
start capture | | end | globally, i.e. not just the first
group | | capture | occurrence on a line
any digit | the first capture
one or group contents
more times
If -i is not supported, just create a new file and replace the old one:
sed ... > newfile
mv oldfile oldfile~ # a backup
mv newfile oldfile
use sed,
sed 's/\(:[0-9]\+\)/\1_suffix/g' file
add -i modifier , if you want to do an in-place edit.

Unix- Sed replacing substring

I am new to sed . I want to replace a substring
for example:
var1=server1:game1,server2:game2,sever3:game1
output should be
server1 server2 server3 (with just spaces)
I have tried this.
echo $var1 | sed 's/,/ /g' | sed 's/:* / /g'
This is not working. Please suggest a solution.
You can try this sed,
echo $var1 | sed 's/:[^,]\+,\?/ /g'
Explanation:
:[^,]\+, - It will match the string from : to ,
\? - Previous may occur or may not ( Since end of line don't have , )
echo $var1 | sed s/:game[0-9],*/\ /
Assuming your sub string has game followed by a number([0-9]*)
An awk variation using same regex as sed
awk '{gsub(/:[^,]+,?/," ")}1' <<< "$var1"
PS Its always good custom to "quote" variables
Just for info, you are really only matching, not replacing, so grep can be your friend (with -P):
grep -oP '[^:,=]+(?=:)'
That matches a number of characters that aren't :,= followed by a : using lookahead.
This will put the servers on different lines, which may be what you want anyway. You can put them on one line by adding tr:
grep -oP '[^:,=]+(?=:)' | tr '\n' ' '

Resources