LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 09-27-2021, 01:11 PM   #1
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,677

Rep: Reputation: Disabled
Double a number with sed


First, some context.

There is an old, but very good vi/ex tutorial series by Walter Alan Zintz. Recently, I stumbled upon a modernized version of it, adapted for Vim usage by Barry Arthur and Israel Chauca: https://dahu.github.io/vim_waz_ere

It's still incomplete, but already useful. Among other topics, they expanded the chapter on the substitute command and even provided some Vim-specific exercises not found in the original series.

One of those exercises deals with the following dataset:
Code:
@items = [
  [1,  2,  3,  4,  5],
  [6,  7,  8,  9,  10],
  [11, 12, 13, 14, 15]
]
There are two questions:

1. What command would remove the 3rd column of numbers?
Unlike sed, ed, edbrowse, vile and elvis, the substitute command in Vim doesn't have the number flag that allows you to specify the Nth match.

So an obvious sed/ed solution s/\s*\w*,//3 won't work in Vim. What they suggest instead is setting the start of the match, an equivalent to lookbehind:
Code:
s/\v/(.{-},){2}\zs.{-},//
A rather inelegant solution compared to sed/ed.
There's a bonus question, too:

2. What command would double the numbers in the third column instead of removing them?
As a solution they suggest using substitute with an expression, a powerful, but somewhat esoteric Vim feature:
Code:
s/\v%(\d+,\s*){2}\zs\d+/\=submatch(0)*2
That got me thinking whether a transformation like this was possible with sed, and what it would look like. Awk is certainly better suited for this kind of task, but that's beyond the point.

My first idea was to use substitute with the e flag, like this:
Code:
sed -E '
  /^\s*\[/{
    h
    s/^([^,]+,){2}([^,]+).*/expr \2 + \2/e
    G
    s/^(.+)\n(([^,]+,){2}\s*)[^,]+/\2\1/
}'
This is probably as practical as it goes with sed.

Of course, there is plenty of information both in the GNU sed manual and at http://sed.sf.net on how to do arithmetic in sed proper, but it's anything other than practical. Nevertheless, after some thought (and using those sources as reference) I came up with this:
Code:
#!/bin/sed -Ef
# Double a natural number
# Carry is indicated by upper case
y/0123456789/abcdeFGHIJ/
s/^[F-J]/A&/
s/[a-e][F-J]/\u&/g
s/[F-J]([a-e]|$)/\l&/gI
y/abcdefghijABCDEFGHIJ/02468024681357913579/
For an example like above, where all numbers are less than 55, this will do as well:
Code:
#!/bin/sed -Ef
# Quick'n'dirty doubling of a number
# Only numbers up to 54 are allowed
/^([0-4]?[0-9]|5[0-4])$/!{
i\
Number out of range. Acceptable are numbers 0 - 54.\
Invalid input occurred at this line:
=
q
}

s/[5-9]/@&/
y/123456789/246802468/
/@/{
  s/$/_8967452301/
  s/(.?)@(.*)_.*\1(.).*/\3\2/
}
The latter script could be modified to work with numbers of any length, but that would involve looping, making it inefficient compared to the upper case technique:
Code:
#!/bin/sed -Ef
# Double a natural number
# @ indicates carry
s/[5-9]/@&/g
y/123456789/246802468/
/@/s/$/_8967452301/
:loop
/@/{
  s/(.?)@(.*_.*\1(.).*)/\3\2/
  b loop
}
/_/s/_.*//
What do you think?

Last edited by shruggy; 09-30-2021 at 05:58 AM.
 
Old 09-27-2021, 05:40 PM   #2
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,146

Rep: Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124Reputation: 4124
quixotic.
 
Old 09-27-2021, 06:35 PM   #3
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,783

Rep: Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214Reputation: 2214
Interesting, but not all that impressive, given the various sed scripts (e.g., dc.sed) that have been written by people with far too much time on their hands.

Now, if someone were to write a sed script that performs the calculations for mining bitcoins, ... .
 
  


Reply

Tags
sed, vim



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to use a float/double without using float/double keyword? geewhan Linux - Kernel 4 06-17-2012 08:19 AM
[SOLVED] Changing pattern using sed [number] to number. xpto09 Linux - General 2 06-22-2011 03:32 PM
Identify and explain the major number, minor number, and revision number in Linux... turbomen Linux - Newbie 1 11-16-2010 02:48 AM
Double Quotes Inside Double Quotes youarefunny Programming 6 06-09-2010 10:21 PM
Double the desktop, not double the fun! bizshop SUSE / openSUSE 3 08-26-2005 12:22 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 12:22 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration