How to update property file values from their character value to its equivalent ASCII value - bash

I have a property file (test.properties) with below contents. The value has only one alphabet
key1=D
k1ey=A
key3=B
I want to update all the property values with their ASCII values.
key1=068
k1ey=065
key3=066
How can I update the property values as shown above and save it to new file (final.properties) in a bash script

Using this BashFAQ-071 How do I convert an ASCII character to its decimal (or hexadecimal) value and back? as reference, you can do a neat little trick as shown below to convert ASCII character to its decimal value.
#!/usr/bin/env bash
while IFS== read -r key value; do
LC_CTYPE=C printf -v decimalValue %03d "'$value"
printf '%s=%s\n' "$key" "$decimalValue"
done < test.properties > final.properties
The idea is we pre-pend the property values with a ' and then printf in-turn converts it to is ASCII equivalent of the value and then we print it out with a format specifier %03d to represent it as decimal value.

If you can use perl it's super simple
perl -pe 's/=\K./ord$&/e' test.properties > final.properties

Related

How do you convert characters to ASCII without use of the printf in bash

ascii() {printf '%d' "'$1"}
I am currently using this function to convert characters to ASCII, however I just want to store the result of the function as a variable without printing the ascii. How would I go about this? (please bear in mind I have only been using bash for a few hours total, so sorry if this is a dumb question.)
In bash, after
printf -v numval "%d" "'$1"
the variable numval (you can use any other valid variable name) will hold the numerical value of the first character of the string contained in the positional parameter $1.
Alternatively, you can use the command substitution:
numval=$(printf "%d" "'$1")
Note that these still use printf but won't print anything to stdout.
As stated in the comment by #Charles Duffy, the printf -v version is more efficient, but less portable (standard POSIX shell does not support the -v option).
Thx for your script! I didn't know how get ascii values so "'M" rescued me.
I pass parameters to function to get return.
Function returns I use to... Well, return err/status codes.
#!/bin/sh
# posix
ascii () {
# $1 decimal ascii code return
# $2 character
eval $1=$(printf '%d' "'$2")
}
ascii cod 'M'
echo "'M' = $cod"

How to replace a string like "[1.0 - 4.0]" with a numeric value using awk or sed?

I have a CSV file that I am piping through a set of awk/sed commands.
Some lines in the CSV file look like this:
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"
where the 8th and 9th columns are a string representing a numeric range.
How can I use awk or sed to replace those fields with a numeric value? Either the beginning of the range, or the end of the range?
So this line would end up as
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,0.384
or
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,3.0,0.768
I got as far as removing the brackets but past that I'm stuck. I considered splitting on the " - ", but many lines in my file have a regular numeric value, not a range, in those last two columns, and that makes things messy (I don't want to end up with some lines having a different number of columns).
Here is a sed command that will take each range and break it up into two fields. It looks for strings like "[A - B]" and converts them to A,B. It can easily be modified to just use one of the values if needed by changing the \1,\2 portion. The regular expression assumes that all numbers have at least one digit on either side of a required decimal place. So, 1, .5, and 3. would not be valid. If you need that, the regex can be made to be more accommodating.
$ cat file
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"
$ sed -Ee 's|"\[([0-9]+\.[0-9]+) - ([0-9]+\.[0-9]+)\]"|\1,\2|g' file
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,3.0,0.384,0.768
Since your data is field-based, awk is the logical choice.
Note that while awk generally isn't aware of double-quoted fields, that is not a problem here, because the double-quoted fields do not have embedded , instances.
#!/usr/bin/env bash
useStart1=1 # set to `0` to use the *end* of the *penultimate* fields' range instead.
useStart2=1 # set to `0` to use the *end* of the *last* field's range instead.
awk -v useStart1=$useStart1 -v useStart2=$useStart2 '
BEGIN { FS=OFS="," }
{
split($(NF-1), tokens1, /[][" -]+/)
split($NF, tokens2, /[][" -]+/)
$(NF-1) = useStart1 ? tokens1[2] : tokens1[3]
$NF = useStart2 ? tokens2[2] : tokens2[3]
print
}
' <<'EOF'
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"
EOF
The code above yields:
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,0.384
Modifying the values of $useStart1 and $useStart2 yields the appropriate variations.

Shell: In-file converting first field of a text file from decimal to hexadecimal

This is my example text file:
$ cat RealVNC\ MRU.reg
"10"="Lamborghini-:1"
"16"="Terminus-"
"20"="Midnighter-:5915"
"35"="ThreepWood-:1"
"81"="Midnighter-:1"
"58"="Midnighter-"
And I would like to convert values of the first field (the numbers between "") from decimal to hexadecimal (it is a .reg file for Windows, so I meesed it up thinking the numbers were in a decimal base, and now the file is too long to manually edit).
Example result that I need to obtain:
$ cat Hex\ RealVNC\ MRU.reg
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"
As can be seen, only the numbers have changed.
Resulting numbers must be two characters long (RegEdit considers them different).
Changes in the order of the lines don't bother here, but I think it would be more "clean" a solution that doesn't change it.
I don't expect any number (be it decimal or hex) will have more than 2 characters, but a solution that considers this possibility will be best (as it is a more generic solution).
I have tested so far:
$ cat RealVNC\ MRU.reg | awk -F \" '{print $2}'
10
16
20
35
81
58
But I don't know who to in-line make the changes from dec to hex.
My shell is usually Bash, but other shell-derivated solutions (like Perl or Python) are accepted too.
A simple awk:
awk -F\" '$2=sprintf("%02X", $2)' OFS=\" file
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"
Explanation
-F\" : sets field separator (FS) to "
$2=sprintf("%02X", $2) : $2 is assigned to it’s printed
version ( sprintf) with a %02X mask in hexadecimal using the
letters 'A' to 'F' for hex digits greater than 9 and a two digits
width with 0 padding
OFS=\" : sets the Output FS to match FS
The $2 assignation is always true and no additional action is given , awk always displays the results as it's default action.
You can use perl - when using the substitution operator with the e flag you can pass a function to handle the replace value:
echo abc | perl -ne 's/(.+)/uc($1);print/e' # ABC
You can then use sprintf function to convert decimal to hex with the %X conversion:
%x an unsigned integer, in hexadecimal
%X like %x, but using upper-case letters
$ cat RealVNC\ MRU.reg | perl -ne 's/^"(.*?)"/sprintf("\"%X\"", $1)/e;print;'
"A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"
If you want leading zero on 0-F single values you can use the prefix format %02X:
%02X
^^L Conversion
|L Result length
L- Prefix char
And the result:
$ cat RealVNC\ MRU.reg | perl -ne 's/^"(.*?)"/sprintf("\"%02X\"", $1)/e;print;'
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"

shell script - is there any way converting number to char? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Integer ASCII value to character in BASH using printf
I want to convert my integer number to ASCII character
We can convert in java like this:
int i = 97; //97 is "a" in ASCII
char c = (char) i; //c is now "a"
But,is there any way in to do this shell scripting?
#!/bin/bash
# chr() - converts decimal value to its ASCII character representation
# ord() - converts ASCII character to its decimal value
chr() {
printf \\$(printf '%03o' $1)
}
ord() {
printf '%d' "'$1"
}
ord A
echo
chr 65
echo
Edit:
As you see ord() is a little tricky -- putting a single quote in front of an integer.
The Single Unix Specification: "If the leading character is a
single-quote or double-quote, the value shall be the numeric value in
the underlying codeset of the character following the single-quote or
double-quote."
(Taken from http://mywiki.wooledge.org/BashFAQ/071).
See man printf(1p).
declare -i i=97
c=$(printf \\$(printf '%03o' $i))
echo "char:" $c

SPRINTF in shell scripting?

I have an auto-generated file each day that gets called by a shell script.
But, the problem I'm facing is that the auto-generated file has a form of:
FILE_MM_DD.dat
... where MM and DD are 2-digit month and day-of-the-month strings.
I did some research and banged it at on my own, but I don't know how to create these custom strings using only shell scripting.
To be clear, I am aware of the DATE function in Bash, but what I'm looking for is the equivalent of the SPRINTF function in C.
In Bash:
var=$(printf 'FILE=_%s_%s.dat' "$val1" "$val2")
or, the equivalent, and closer to sprintf:
printf -v var 'FILE=_%s_%s.dat' "$val1" "$val2"
If your variables contain decimal values with leading zeros, you can remove the leading zeros:
val1=008; val2=02
var=$(printf 'FILE=_%d_%d.dat' $((10#$val1)) $((10#$val2)))
or
printf -v var 'FILE=_%d_%d.dat' $((10#$val1)) $((10#$val2))
The $((10#$val1)) coerces the value into base 10 so the %d in the format specification doesn't think that "08" is an invalid octal value.
If you're using date (at least for GNU date), you can omit the leading zeros like this:
date '+FILE_%-m_%-d.dat'
For completeness, if you want to add leading zeros, padded to a certain width:
val1=8; val2=2
printf -v var 'FILE=_%04d_%06d.dat' "$val1" "$val2"
or with dynamic widths:
val1=8; val2=2
width1=4; width2=6
printf -v var 'FILE=_%0*d_%0*d.dat' "$width1" "$val1" "$width2" "$val2"
Adding leading zeros is useful for creating values that sort easily and align neatly in columns.
Why not using the printf program from coreutils?
$ printf "FILE_%02d_%02d.dat" 1 2
FILE_01_02.dat
Try:
sprintf() { local stdin; read -d '' -u 0 stdin; printf "$#" "$stdin"; }
Example:
$ echo bar | sprintf "foo %s"
foo bar

Resources