Increment and decrements numbers - search

I have this text with numbers:
My numbers are 04, and 0005
My numbers are 05, and 0006
My numbers are 06, and 0035
My numbers are 07, and 0007
My numbers are 08, and 0009
This is the code I always used to increment or decrement numbers in a selection/block selection/column:
p.e. increment the last 4 numbers in above text with 8:
'<,'>s/\%V\<\d\{4}\>/\=submatch(0)+8/g
but I noted today that it does strange things.
This is the output:
My numbers are 04, and 13
My numbers are 05, and 14
My numbers are 06, and 37 <---
My numbers are 07, and 15
My numbers are 08, and 17
it removes the leading zero's ( I would like to keep them if there are leading zero's
and not add them if there aren't leading zero's)
it added 8 to all numbers except 37, where it added 2. (why?)
Can anyone help me to find a regex to add /subtract numbers
from selection (or block selection) without losing the leading zero's?
note:
I noted that Control A + Control x keeps the leading zero's and does the work as I want but:
- I've seen that it can not be used in a substitute command ('<,'>s/)
- and I don't know how to add p.e. 200 to a list of numbers (200 x ?)

leading zero makes number 8-based.
(0035)8 == (29)10
You can test in vim:
:echo 0035 == 29
It'll print 1(true).
Try this:
:%s/\(\<[0-9]\{4}\>\)\#=0*\([0-9]*\)/\=submatch(2)+8/

this?
:%s/\v[0-9]{4}/\=printf("%04d", substitute(submatch(0), '^0\+', '', 0)+8)/
EDIT
#Remonn, you should give the right sample input in your question. the line above works on your example.
for your new requirement, take a look the line below:
input:
40
20
120
0500
230
0000000020
00000000000005000
vim cmd:
:%!awk '{if($0~/^0/){f="\%"length($0)"d";$0+=8; s=sprintf(f,$0); gsub(/ /,"0",s);}else s=$0+8;print s}'
will change the file to:
48
28
128
0508
238
0000000028
00000000000005008
in my cmd, I used '%', you can select (v) the numbers you want to do tricks with, then try with my cmd.
good luck

By default, Vim treats numbers beginning with 0 as octal.
For this reason I have this in my .vimrc:
set nrformats-=octal " Don't bother with octal, I never use it

Related

Extract number from column

i have a lot of address data in (mostly) this format:
Karl-Reimann-Ring 13, 99087 Erfurt
Markttwiete 2, 23611 Bad Schwartau
Hüxstraße 55, 23552 Lübeck
Bunsenstraße 1c, 24145 Kiel
and my goal is to extract the zip code.
I copied a formula from a website, which i dont really understand:
=VERWEIS(9^9;1*TEIL(E2861&"#";SPALTE(2860:2860);6))
VERWEIS = LOOKUP,
TEIL = MID,
SPALTE = COLUMN
This formula seems to work 99% of the time, also for the ones above, but for some i get weird results.
Kurt-Schumacher-Straße 56, 55124 Mainz --> 44340
Kleine Früchtstraße 6, 55130 Mainz --> 44346
Bahnstraße 1, 55128 Mainz --> 44344
All with 'Mainz' are wrong and start with 44xxx
But when i increase the last argument from 6 to 7 it seems to work.
Do somebody know, how i can impove this formula to get always the correct zip code?
The problem is that the formula will return the last "number" which is constructed of 6 character strings starting at every character in the string.
The last substring that can be interpreted numerically (in the 55424 Mainz address) is actually 24 Mai. German Excel will parse that into 24 Mai 2021 which, as a number, will be 44340.
One modification you can make to your formula, to prevent that from happening, would be to add a comma after the zipcode. eg:
=LOOKUP(9^9;1*MID(SUBSTITUTE(A1;" ";",") & "#";COLUMN(2860:2860);6))
Another option would be to use FILTERXML where you can separate by spaces, and then return the last numeric node:
=FILTERXML("<t><s>" &SUBSTITUTE(A1;" ";"</s><s>") & "</s></t>";"//s[number(.) = number(.)][last()]")

Concatenate strings in COBOL without leading or trailing spaces

I'm having issues with this task; our task is to concatenate 2 strings without spaces in between those two, e.g.:
Input Alphanum. . 1: This string is
Input Alphanum. . 2: concatenated.
Input Alphanum. . 3:
Alphanum. output 1: This string isconcatenated.
Alphanum. output 2:
I can get these 2 strings together into the output, but they wont attach to each other without the spaces in between.
so assuming you don't know the length of the two strings, you would need to do something like this:
01 WS-INPUT-STRINGS.
05 WS-STRING1 PIC X(100) VALUE "THIS STRING IS".
05 WS-STRING2 PIC X(100) VALUE "CONCATENATED".
05 WS-STRING3 PIC X(100) VALUE SPACES.
01 WS-OUTPUT-STRINGS.
05 WS-CONCATENATED-OUTPUT PIC X(300) VALUE SPACES.
01 WS-COUNTERS.
05 WS-LEN-IN PIC 9(4) COMP VALUE 1.
05 WS-POS PIC 9(4) COMP VALUE 1.
IF WS-STRING1 NOT EQUAL SPACES OR LOW-VALUES
PERFORM VARYING WS-LEN-IN
FROM 100 BY -1
UNTIL WS-STRING1(WS-LEN-IN:1)
NOT EQUAL (SPACES OR LOW-VALUES) OR
WS-LEN-IN = 1
END-PERFORM
MOVE WS-STRING1(1:WS-LEN-IN)
TO WS-CONCATENATED-OUTPUT(WS-POS:WS-LEN-IN)
ADD WS-LEN-IN TO WS-POS
END-IF
IF WS-STRING2 NOT EQUAL SPACES OR LOW-VALUES
PERFORM VARYING WS-LEN-IN
FROM 100 BY -1
UNTIL WS-STRING2(WS-LEN-IN:1)
NOT EQUAL (SPACES OR LOW-VALUES) OR
WS-LEN-IN = 1
END-PERFORM
MOVE WS-STRING2(1:WS-LEN-IN)
TO WS-CONCATENATED-OUTPUT(WS-POS:WS-LEN-IN)
ADD WS-LEN-IN TO WS-POS
END-IF
IF WS-STRING3 NOT EQUAL SPACES OR LOW-VALUES
PERFORM VARYING WS-LEN-IN
FROM 100 BY -1
UNTIL WS-STRING3(WS-LEN-IN:1)
NOT EQUAL (SPACES OR LOW-VALUES) OR
WS-LEN-IN = 1
END-PERFORM
MOVE WS-STRING3(1:WS-LEN-IN)
TO WS-CONCATENATED-OUTPUT(WS-POS:WS-LEN-IN)
ADD WS-LEN-IN TO WS-POS
END-IF
DISPLAY WS-CONCATENATED-OUTPUT(1:WS-POS)
You could put this into a paragraph and perform it over and over, but I did it this way to illustrate exactly what it going on. When you define a picture clause in COBOL, it will always to that length, so if I just tried to string the 3 variables together, there would be tons of extra space between them because each picture clause is 100 characters long regardless of what I put in them. I use these loops to calculate the length of each variable. First I check to make sure there is something in the variable, then loop backwards until I find a character.
You did not say if you needed to trim leading spaces as well, so I just assumed trailing spaces only. You could also you use INSPECT TALLYING to get the count rather than writing the loops
Use the UNSTRING command with the TALLYING IN and WITH POINTER options to keep track of where you want to put the next string.

Trying to remove only the characters F or C following numbers

I'm trying to find a regex (that will work in node.js) to remove the Fahrenheit and Celsius letters and replace them with " degrees" from the below weather forecast string.
"Clear skies. Low 46F. NNW winds shifting to ENE at 10 to 15 mph."
I want the above string to read as below:
"Clear skies. Low 46 degrees. NNW winds shifting to ENE at 10 to 15 mph."
There could be more than one instance of a temperature in the string.
NOTE: I only want to remove the F or C if it's immediately following a number with no space in-between. If "Florida" were in the above string, I'd want the letter "F" left untouched.
I've tried the below regex, but it finds the entire 46F. I just want it changed to 46 degrees.
/\d+[FC]/g
Thanks.
That is because the lack of the capturing group (parentheses):
Use this:
/(\d+)[FC]/g
$1 means the first capturing group. The \d+ in this case.
speechOutput = speechOutput.replace(/(\d+)[FC]/g, '$1 degrees');

Vim incorrectly removes zeros when decrementing

Vim removes zeros from in front of some digits when decrementing:
If I take a text file with the following:
a02
a03
a04
a05
a06
a07
a08
a09
a10
a11
And use ctrl+V to highlight the second and third columns, and then hit ctrl+X to decrement, I am left with:
a01
a02
a03
a04
a05
a06
a7
a8
a9
a10
I am running Vim version 7.4.1689 and I loaded it without my .vimrc via
$ vim -u NONE
This is happening because Vim will automatically recognize and convert octal values.
From the help (:h variables):
Conversion from a Number to a String is by making the ASCII representation of
the Number.
Examples:
Number 123 --> String "123"
Number 0 --> String "0"
Number -1 --> String "-1"
Conversion from a String to a Number is done by converting the first digits to
a number. Hexadecimal "0xf9", Octal "017", and Binary "0b10" numbers are
recognized. If the String doesn't start with digits, the result is zero.
Examples:
String "456" --> Number 456
String "6bar" --> Number 6
String "foo" --> Number 0
String "0xf1" --> Number 241
String "0100" --> Number 64
String "0b101" --> Number 5
String "-8" --> Number -8
String "+8" --> Number 0
Your values 02 through 07 are being recognized as valid octal values and preserved as such, decremented to octal 01 through 06.
When you reach 08 it is not a valid octal value. It is treated as the string 08, converted to decimal value 8, and decremented to 7. This happens again with 09, which ends up being 8.
The 10 and 11 values are decremented as decimal as well. Because 10 was decimal, not octal, you don't get a leading 0 in the resulting 9 value.
I'm not aware of a way to do what you want with the decrement command.
EDIT: After finding this answer, I tested this expression and it does what you are trying to do in this specific case:
:%s/\v[0-9]+/\=printf("%02d", substitute(submatch(0), '^0\+', '', 0)-1)/
I'm not sure whether this solves your general use case, because it's quite different from the original operation using a selection. But for the file you provided, it achieves the result you were after.
Dissecting this a bit to explain it:
First we start by calling the global sub command %s and passing the \v flag to turn on "very magic" mode. This may or may not change the behavior depending on your settings, but this is a public example, so it is included here to ensure that mode is active.
:%s/\v
Then, we find all the contiguous sequences of digits. This will find 02, 03, and so on from your example.
[0-9]+
Then in the replacement portion we have this command, which does the real work:
\=printf("%02d", substitute(submatch(0), '^0\+', '', 0)-1)
The substitute() function determines what the new value is. submatch(0) means to use the entire match. Using a pattern of ^0\+ and a replacement of (empty string) says to strip the leading zero from any number which has one. The 0 at the end isn't too important; it just says there are no flags to the substitute() function.
The result of the substitute command is a number. Say 02 has been stripped down to be 2. Using the - 1 at the end, we subtract 1 from that result (decrement).
Finally, this result is passed to the printf function. Using a format string %02d says to print the values as decimal, in 2-digit wide format, padding with leading zeroes.
If you want Vim to treat all numbers as decimals, you may want to add the following line to your .vimrc:
set nrformats=

ASCII text to Hexadecimal in Excel

I want to this but i don't know what to do, the only functions it seems to be useful is "DEC.TO.HEX".
This is the problem, i have in one cell this text:
1234
And in the next cell i want the hexadecimal value of each character, the expected result would be:
31323334
Each character must be represented by two hexadecimal characters. I don't have an idea how to solve this in excel avoiding make a coded program.
Regards!
Edit: Hexadecimal conversion
Text value Ascii Value (Dec) Hexadecimal Value
1 49 31
2 50 32
3 51 33
4 52 34
Please try:
=DEC2HEX(CODE(MID(A1,1,1)))&DEC2HEX(CODE(MID(A1,2,1)))&DEC2HEX(CODE(MID(A1,3,1)))&DEC2HEX(CODE(MID(A1,4,1)))
In your version you might need the .s in the function (and perhaps ;s rather than ,s).
DEC2HEX may be of assistance. Use, as follows:
=DEC2HEX(A3)
First split 1234 to 1 2 3 4 by using MID(), then use Code() for each character, and then again concentate. Below is the formula, Y21 is the cell in which 1234 is written
=CONCATENATE(CODE(MID(Y21,1,1)),CODE(MID(Y21,2,1)),CODE(MID(Y21,3,1)),CODE(MID(Y21,4,1)))
1234 >> 49505152

Resources