LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 12-02-2012, 07:31 PM   #1
masavini
Member
 
Registered: Jun 2008
Posts: 196

Rep: Reputation: 6
sed recursive substitution...


hi,
i need to edit some strings so that ending zeros are substituted by "[0-9]", one for each zero:
Code:
$ echo "10" | someSedCommand
1[0-9]
$ echo "100" | someSedCommand
1[0-9][0-9]
$ echo "1000" | someSedCommand
1[0-9][0-9][0-9]
$ echo "10000" | someSedCommand
1[0-9][0-9][0-9][0-9]
don't even know what to start with... thanks for your help...
 
Old 12-02-2012, 09:03 PM   #2
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,167

Rep: Reputation: 306Reputation: 306Reputation: 306Reputation: 306
Try this ...
echo "10000" |sed 's/0/[0-9]/g'

Daniel B. Martin
 
Old 12-02-2012, 09:05 PM   #3
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
I assume that you mean that the literal [0-9] is to be substituted. You want the SED s (substitute) command

Code:
[mherring@herring_lap ~]$ echo "1000" |sed 's/0/[0-9]/g'
1[0-9][0-9][0-9]
[mherring@herring_lap ~]$ echo "100" |sed 's/0/[0-9]/g'
1[0-9][0-9]
[mherring@herring_lap ~]$
 
Old 12-02-2012, 09:06 PM   #4
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
Oops,I was wordsmithing while Daniel was producing results......
 
Old 12-03-2012, 12:45 AM   #5
towheedm
Member
 
Registered: Sep 2011
Location: Trinidad & Tobago
Distribution: Debian Squeeze
Posts: 585

Rep: Reputation: 119Reputation: 119
Bug report

I'll use 'a' as the replacement string:
Code:
echo "1000" | sed 's/0/a/g'
1aaa
But since the OP wants to match only 'ending zeroes':
Code:
echo "1001000" | sed 's/0/a/g'
1aa1aaa
I'll be damned if I figure it out this time, as I could never get the regex right to replace each occurrence of a specific character at the end of string with another. Maybe this thread will show me the way, ie:
Code:
echo "1001000" | sed 's/replace all 0's at end/with a/'
1001aaa
 
Old 12-03-2012, 02:49 AM   #6
masavini
Member
 
Registered: Jun 2008
Posts: 196

Original Poster
Rep: Reputation: 6
hi,
towheedm is right...
only ENDING zeros should be substituted...
i thought about it last night, but could not get anything...
 
Old 12-03-2012, 05:00 AM   #7
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 640

Rep: Reputation: 375Reputation: 375Reputation: 375Reputation: 375
Hi.

Code:
$ echo 100123000  | sed -r ':a; s/0(:*)$/:\1/;ta; s/:/[0-9]/g' 
100123[0-9][0-9][0-9]
Here we substitute each 0 at the end by a placeholder (a colon : ) using an explicit loop (:a ... ta) and then substitute every : by a '[0-9]'.

Of course we could do the same in a single step, ending with the following mess:
Code:
$ echo 100123000  | sed -r ':a; s/0((\[0\-9\])*)$/[0-9]\1/;ta;' 
100123[0-9][0-9][0-9]
Another approach is to use hold space:
Code:
$ echo 100123000  | sed -r 'h; s/.*[^0]//; s/0/[0-9]/g; x; G; s/0*\n//;' 
100123[0-9][0-9][0-9]
This may be translated as:
1. remember whole string in hold space (h)
2. remove everything except trailing zeros (s/.*[^0]//)
3. replace each zero by [0-9]
4. exchange pattern and hold spaces (x)
5. append hold space to pattern space (G). Pattern space: "100123000\n[0-9][0-9][0-9]"
6. remove sequence of zeros ending with newline.

Last edited by firstfire; 12-03-2012 at 05:16 AM.
 
2 members found this post helpful.
Old 12-03-2012, 09:52 AM   #8
masavini
Member
 
Registered: Jun 2008
Posts: 196

Original Poster
Rep: Reputation: 6
just perfect... thank you!
 
Old 12-03-2012, 11:01 PM   #9
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,167

Rep: Reputation: 306Reputation: 306Reputation: 306Reputation: 306
Quote:
Originally Posted by masavini View Post
i need to edit some strings so that ending zeros are substituted by "[0-9]"...
Perhaps you know certain characteristics of your data.
For example, you might know that the number of trailing zeros is 4, at most.
If so you could use a "brute force" sed.

Input file:
Code:
1002
10030
100400
1005000
10060000
This sed ...
Code:
sed 's/0000$/[0-9][0-9][0-9][0-9]/;s/000$/[0-9][0-9][0-9]/;s/00$/[0-9][0-9]/;s/0$/[0-9]/' $InFile
Produces this result ...
Code:
1002
1003[0-9]
1004[0-9][0-9]
1005[0-9][0-9][0-9]
1006[0-9][0-9][0-9][0-9]
Daniel B. Martin
 
Old 12-04-2012, 09:39 AM   #10
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,167

Rep: Reputation: 306Reputation: 306Reputation: 306Reputation: 306
Quote:
Originally Posted by masavini View Post
i need to edit some strings so that ending zeros are substituted by "[0-9]" ...
OP asked for a sed solution and several have been offered. I'm learning awk and cooked up this one ...
Code:
awk -F "" 'BEGIN{OFS="";}{for (j=NF;j>=1;j--) if ($j==0) $j="[0-9]"; else break;} 1' $InFile
Experienced awkers are invited to show how this can be tightened. Thank you.

Daniel B. Martin
 
Old 12-05-2012, 09:27 PM   #11
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950
By "ending zeros", do you mean the end of the line, or the end of a number only? And can there be multiple numbers on a line, or extra text after the number?

Assuming the latter, how about an awk solution instead?

Code:
awk '{ for ( i=1; i<=NF; i++ ) { if ($i ~ /^10+$/) { gsub("0","[0-9]",$i) } } print }'
for ( i=1; i<=NF; i++ ) {..} == loop over every field in the line (and run the given sub-commands).
if ($i ~ /^10+$/) {..} == test that the field exactly matches 1 + one or more 0's (and run subcommand).
{ gsub("0","[0-9]",$i) } == replace all zeroes in the field with [0-9].
print == print the line, naturally.

Code:
#input:
10
100
1000
foo 100 bar
foo 100 100x00
foo

#output:
1[0-9]
1[0-9][0-9]
1[0-9][0-9][0-9]
foo 1[0-9][0-9] bar
foo 1[0-9][0-9] 100x00
foo
Edit: frak, I somehow completely missed daniel's post just above this one! Oh well, at least my solution is substantially different.

Last edited by David the H.; 12-05-2012 at 09:37 PM.
 
Old 12-06-2012, 11:17 AM   #12
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,167

Rep: Reputation: 306Reputation: 306Reputation: 306Reputation: 306
Quote:
Originally Posted by danielbmartin View Post
In a previous post I offered this awk solution ...
Code:
awk -F "" 'BEGIN{OFS="";}{for (j=NF;j>=1;j--) if ($j==0) $j="[0-9]"; else break;} 1' $InFile
I reworked this one-liner to use the awk ternary operator ...
Code:
awk -F "" 'BEGIN{OFS="";}{for (j=NF;j>=1;j--) $j==0? $j="[0-9]": break;} 1' $InFile
... but this fails with a syntax error. Why?

I circumvented the syntax error by coding this variation ...
Code:
awk -F "" 'BEGIN{OFS="";}{for (j=NF;j>=1;j--) $j==0? $j="[0-9]": j=0;} 1' $InFile
... which works.

Next step, to reduce the number of keystrokes ...
Code:
awk -F "" 'OFS="";{j=NF;while(!$j){$j="[0-9]";j--}}1' $InFile
This version is concise but less readable.


Daniel B. Martin

Last edited by danielbmartin; 12-06-2012 at 12:44 PM. Reason: Tighten the code, slightly
 
Old 12-06-2012, 01:13 PM   #13
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950
The ternary operator is a conditional expression which, AIUI, after evaluation expands to a specific value. It's not designed for evaluating commands.

http://www.gnu.org/software/gawk/man...ional-Exp.html

I don't imagine that the performance would be significantly improved with a while loop, but it does seem to make the code a bit cleaner.

Code:
awk '{ j=NF ; while ( $j==0 ) { $j="[0-9]" ; j-- } }1' FS='' OFS='' infile
The only real criticism I have with this is that it doesn't do any testing to match the conditions as stated in the OP, and simply replaces any zeros that appear at the end of the line. Otherwise I like the concept.
 
1 members found this post helpful.
Old 12-06-2012, 01:30 PM   #14
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,167

Rep: Reputation: 306Reputation: 306Reputation: 306Reputation: 306
Quote:
Originally Posted by David the H. View Post
It's not designed for evaluating commands.
Thank you for this explanation. I had naively imagined that the awk ternary operator was only a different notation, and fully compatible with if-else.
Quote:
The only real criticism I have with this is that it doesn't do any testing to match the conditions as stated in the OP, and simply replaces any zeros that appear at the end of the line.
I don't follow this. What testing did OP request? I read it (or misread it) to call for nothing more than replacement of trailing zeros.

The awk code was undertaken as a learning exercise, and it turned out to be a beneficial one. Now I have a better "feel" for the ternary operator.

Daniel B. Martin
 
Old 12-06-2012, 03:09 PM   #15
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950
Hm, perhaps you're right, and I was the one reading too much into the initial request. But I still have the impression that he wanted something more detailed, which is why I asked for further clarification in my first post.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] sed substitution not working flyscubakev Linux - Newbie 3 07-26-2011 11:18 AM
SH: Recursive Variable Substitution TVT Programming 7 07-01-2010 04:30 PM
SED - substitution carolflb Linux - Newbie 5 02-06-2010 01:20 AM
sed substitution with p flag 7stud Linux - Newbie 2 03-03-2007 05:15 AM
sed substitution error BlkPoohba Programming 1 08-25-2004 03:00 PM


All times are GMT -5. The time now is 01:05 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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration