0

Background information: Data exchange via csv between 2 programs.

I have the following csv from program 1:

> timestamp; name ; value 
> 1655709562;Var 1 Float;65.0 
> 1655709562;Var 2 Float;3.32 
> 1655709562;Var 1 Integer;**2** 
> 1655709562;Var 2 Integer;**564**

For program 2 I have to convert it to the following, because it always expects the same datentype at "value":

timestamp; name ; value
1655709562;Var 1 Float;65.0
1655709562;Var 2 Float;3.32
1655709562;Var 1 Integer;**2.0**
1655709562;Var 2 Integer;**564.0**

I'll try to show it with a for loop and an if function, because I think that's the best way to show it.

for $line in $file
do
 If $line contains NOT "." 
  then
    add ".0" at the end of line
 end_if
done
1
  • If the *** are not part of your file, please remove them. Also, do you just need to change the number, or do you also need to change the type (Integer => Float)?
    – terdon
    Jun 20 at 9:34

1 Answer 1

1

In sed, the syntax for that is:

sed '/\./!s/$/.0/' < file.in > file.out

That is, if the current line does not (!) match the \. regex (a literal dot), substitute the first match of the $ regex ($ matches at the end of the line) with XX.

Same with awk:

awk '! index($0, ".") {$0 = $0 ".0"}
     {print}' < file.in > file.out

Here using index() to do a substring search. You could also do a regexp matching like with sed with ! /\./ instead.

With perl:

perl -lpe '$_ .= ".0" if index($_, ".") < 0' < file.in > file.out

Or with regexps:

perl -lpe '$_ .= "XX" unless /\./' < file.in > file.out

With perl, you can add the -i option to edit the file in place (in which case you have to pass its path as argument instead of opening it on its stdin). Some sed implementations have borrowed that option. Recent versions of the GNU implementation of awk has -i inplace for that.

In all those, a .0 would also be added to the header line as as that line doesn't contain .s either.

Maybe a better way would be to add .0 if the line ends in ; followed by one or more decimal digits:

sed '/;[0123456789]\{1,\}$/ s/$/.0/'

Or with some seds:

sed -E '/;[0123456789]+$/ s/$/.0/'
awk '/;[0123456789]+/{$0 = $0 ".0"}
     {print}'
perl -lpe '$_ .= ".0" if /;\d+$/'
2
  • Thanks for the quick and detailed help. I have used the following string: sed '/\./!s/$/\.0/' -i $file I have included the header only for explanation. Normally it does not exist in the CSV file
    – MarAlz
    Jun 20 at 9:21
  • @MarAlz, the correct syntax in sh and with GNU sed would be sed -i -- '/\./!s/$/.0/' "$file" or sed -i -e '/\./!s/$/.0/' -- "$file". Options should go before non-option arguments. In sh/bash, parameter expansions must be quoted. -- should be used to mark the end of options, . should not be escaped in the replacement, using \. there would yield unspecified behaviour. Jun 20 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.