Unix Shell - sed conversion of digits to "x"

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > November 2005 > sed conversion of digits to "x"





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author sed conversion of digits to "x"
RolandRB

2005-11-22, 5:56 pm

How do I convert digits to "x"s when they have two spaces in front and
two spaces at back (or I don't want them converted) and be of varying
number of digits and maybe have a period in there somewhere (the period
must stay the same) such that (underscore character denotes space). My
"sed" knowledge isn't up to it.

__123__ becomes __xxx__
__134.5__ becomes __xxx.x__
__1__ becomes __x__
__12345.6__ becomes __xxxxx.x__
__6.44__ becomes __x.xx__

Thanks

Stephane CHAZELAS

2005-11-22, 5:56 pm

2005-11-22, 08:09(-08), RolandRB:
> How do I convert digits to "x"s when they have two spaces in front and
> two spaces at back (or I don't want them converted) and be of varying
> number of digits and maybe have a period in there somewhere (the period
> must stay the same) such that (underscore character denotes space). My
> "sed" knowledge isn't up to it.
>
> __123__ becomes __xxx__
> __134.5__ becomes __xxx.x__
> __1__ becomes __x__
> __12345.6__ becomes __xxxxx.x__
> __6.44__ becomes __x.xx__

[...]

Something like:

sed '
:1
/ [0-9]*\(\.[0-9][0-9]*\)\{0,1\} / {
s//\
&\
/
h
s/.*\n\(.*\)\n.*/\1/
s/[0-9]/x/g
G
s/\(.*\)\n\(.*\)\n.*\n/\2\1/
b1
}'

--
Stéphane
RolandRB

2005-11-22, 5:56 pm


Stephane CHAZELAS wrote:
> 2005-11-22, 08:09(-08), RolandRB:
> [...]
>
> Something like:
>
> sed '
> :1
> / [0-9]*\(\.[0-9][0-9]*\)\{0,1\} / {
> s//\
> &\
> /
> h
> s/.*\n\(.*\)\n.*/\1/
> s/[0-9]/x/g
> G
> s/\(.*\)\n\(.*\)\n.*\n/\2\1/
> b1
> }'
>
> --
> St=E9phane


Thanks but when I tried it I got a "command garbled" for s//\

Can you point me to a tutorial as I am not aware of this sort of use of
sed?

Stephane CHAZELAS

2005-11-22, 5:56 pm

2005-11-22, 08:40(-08), RolandRB:
[...]
>
> Thanks but when I tried it I got a "command garbled" for s//\
>
> Can you point me to a tutorial as I am not aware of this sort of use of
> sed?


You need a POSIX conformant sed.

s/a/\
/

replaces "a" with a newline character.

You'll find all the information you need in the manpage.

--
Stéphane
dan.rickhoff@comcast.net

2005-11-22, 5:56 pm

RonaldRB,

You didn't mention wher those strings are located. Here's an example
of how you might do the conversion using only ksh93 built-ins:

print '__123__zzz__134.5__zzz
zzz__1__zzz__12345.6__
zz__6.44__z' | \
while IFS='
' read theWholeLine
do
print -r "${theWholeLine//[0-9]/x}"
done
__xxx__zzz__xxx.x__zzz
zzz__x__zzz__xxxxx.x__
zz__x.xx__z

Ed Morton

2005-11-22, 5:56 pm



RolandRB wrote:

> How do I convert digits to "x"s when they have two spaces in front and
> two spaces at back (or I don't want them converted) and be of varying
> number of digits and maybe have a period in there somewhere (the period
> must stay the same) such that (underscore character denotes space). My
> "sed" knowledge isn't up to it.
>
> __123__ becomes __xxx__
> __134.5__ becomes __xxx.x__
> __1__ becomes __x__
> __12345.6__ becomes __xxxxx.x__
> __6.44__ becomes __x.xx__
>
> Thanks
>


Looks like you already got a sed solution from Stephane, but FYI, here's
how to do it in awk, which may be a bit more readable if you're not
proficient in sed:

$ cat repnrs.awk
function extract(str,regexp) {
RMATCH = (match(str,regexp) ? substr(str,RSTART,RLENGTH) : "")
return RSTART
}
{
while ( extract($0," [0-9]+([.][0-9]+)? ") ) {
rep = RMATCH
gsub(/[0-9]/,"x",rep)
sub(RMATCH,rep)
}
}
1
$ awk -f repnrs.awk file

Regards,

Ed.

Ed Morton

2005-11-22, 5:56 pm



dan.rickhoff@comcast.net wrote:

> RonaldRB,
>
> You didn't mention wher those strings are located. Here's an example
> of how you might do the conversion using only ksh93 built-ins:
>
> print '__123__zzz__134.5__zzz
> zzz__1__zzz__12345.6__
> zz__6.44__z' | \
> while IFS='
> ' read theWholeLine
> do
> print -r "${theWholeLine//[0-9]/x}"
> done
> __xxx__zzz__xxx.x__zzz
> zzz__x__zzz__xxxxx.x__
> zz__x.xx__z
>


Nice try, but that'll just replace every digit no matter whether or not
it fits the desired pattern, e.g.:

$ print 'a7c' |
while IFS='
' read theWholeLine
do
print -r "${theWholeLine//[0-9]/x}"
done
axc

and please read this before posting again:

http://cfaj.freeshell.org/google

Regards,

Ed.
Michael Heiming

2005-11-22, 5:56 pm

In comp.unix.shell Ed Morton <morton@lsupcaemnt.com>:


> RolandRB wrote:


[vbcol=seagreen]
> Looks like you already got a sed solution from Stephane, but FYI, here's
> how to do it in awk, which may be a bit more readable if you're not
> proficient in sed:


> $ cat repnrs.awk
> function extract(str,regexp) {
> RMATCH = (match(str,regexp) ? substr(str,RSTART,RLENGTH) : "")
> return RSTART
> }
> {
> while ( extract($0," [0-9]+([.][0-9]+)? ") ) {
> rep = RMATCH
> gsub(/[0-9]/,"x",rep)
> sub(RMATCH,rep)
> }
> }
> 1
> $ awk -f repnrs.awk file


awk '{gsub("[0-9]","x",$0);print}' infile

Seems to do as fine, as least with gawk for me.

--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 42: spaghetti cable cause packet failure
Ed Morton

2005-11-22, 5:56 pm



Michael Heiming wrote:
<snip>
[vbcol=seagreen]
> awk '{gsub("[0-9]","x",$0);print}' infile
>
> Seems to do as fine, as least with gawk for me.


No, it doesn't restrict the replacement to just the pattern the OP wants
matched.

Ed.
Michael Heiming

2005-11-22, 5:56 pm

In comp.unix.shell Ed Morton <morton@lsupcaemnt.com>:


> Michael Heiming wrote:
> <snip>


[vbcol=seagreen]
> No, it doesn't restrict the replacement to just the pattern the OP wants
> matched.


Yep, rereading the OP.

--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 267: The UPS is on strike.
Bruce Barnett

2005-11-22, 5:56 pm

"RolandRB" <rolandberry@hotmail.com> writes:

> Can you point me to a tutorial as I am not aware of this sort of use of
> sed?


My sed tutorial is here:

http://www.grymoire.com/Unix/index.html

Good luck...


--
Sending unsolicited commercial e-mail to this account incurs a fee of
$500 per message, and acknowledges the legality of this contract.
Bill Marcum

2005-11-22, 5:56 pm

On 22 Nov 2005 08:40:17 -0800, RolandRB
<rolandberry@hotmail.com> wrote:
>
> Thanks but when I tried it I got a "command garbled" for s//\
>
> Can you point me to a tutorial as I am not aware of this sort of use of
> sed?
>

Which shell are you using? If it is csh or tcsh, you might need another
'' at the end of the line.


--
All truths are true to an extend, including this one. -XA
James

2005-11-22, 5:56 pm

In perl,
$ cat conv.pl
sub f {
my $s = shift; $s =~ s/\d/x/g; return $s
}
while (1) {
if (/ [\d\.]+ /) {
print $`.f($&); s/^$`$&//
} else {
print; last
}
}

$ echo " 12.3 a1b2 foo12 3.4 5.67 " | PERL -n conv.pl
xx.x a1b2 foo12 x.x 5.67

James

Ed Morton

2005-11-22, 8:53 pm

James wrote:
> In perl,
> $ cat conv.pl
> sub f {
> my $s = shift; $s =~ s/\d/x/g; return $s
> }
> while (1) {
> if (/ [\d\.]+ /) {
> print $`.f($&); s/^$`$&//
> } else {
> print; last
> }
> }
>
> $ echo " 12.3 a1b2 foo12 3.4 5.67 " | PERL -n conv.pl
> xx.x a1b2 foo12 x.x 5.67


Ahem: notice that final 5.67 in your output....

Ed.
Ed Morton

2005-11-22, 8:53 pm

Ed Morton wrote:

> James wrote:
>
>
>
> Ahem: notice that final 5.67 in your output....


It'll also wrongly convert " 1.2.3 " to " x.x.x ".

Ed.
James

2005-11-22, 8:53 pm

Ahem: notice that final 5.67 in your output....

Ed.

I did that on purpose.
Notice that there are only 3 spaces between 3.4 and 5.67. The first 2
spaces are used up by 3.4,
so 5.67 does not have 2 spaces needed for conversion.

James

John W. Krahn

2005-11-22, 8:53 pm

RolandRB wrote:
> How do I convert digits to "x"s when they have two spaces in front and
> two spaces at back (or I don't want them converted) and be of varying
> number of digits and maybe have a period in there somewhere (the period
> must stay the same) such that (underscore character denotes space). My
> "sed" knowledge isn't up to it.
>
> __123__ becomes __xxx__
> __134.5__ becomes __xxx.x__
> __1__ becomes __x__
> __12345.6__ becomes __xxxxx.x__
> __6.44__ becomes __x.xx__


perl -pe's!(?<= )(\d+(?:\.\d+)?)(?= )!($a=$1)=~y/0-9/x/;$a!eg'


John
--
use Perl;
program
fulfillment
Ed Morton

2005-11-22, 8:53 pm

James wrote:

> Ahem: notice that final 5.67 in your output....
>
> Ed.
>
> I did that on purpose.
> Notice that there are only 3 spaces between 3.4 and 5.67. The first 2
> spaces are used up by 3.4,
> so 5.67 does not have 2 spaces needed for conversion.


Well, looks like you're on to something:

$ echo "1 2 3 4" | sed 's/ [0-9] / X /g'
1 X 3 4
$ echo "1 2 3 4" | awk 'gsub(/ [0-9] /," X ")'
1 X 3 4
$ echo "1 2 3 4" | awk '{while(gsub(/ [0-9] /," X "));}1'
1 X X 4

Wonder what the OP actually wanted....

Ed.
James

2005-11-22, 8:53 pm

Ahem: notice that final 5.67 in your output....

It'll also wrongly convert " 1.2.3 " to " x.x.x ".

Ed.

Thanks for pointing these out.

sub f {
my $s = shift; $s =~ s/\d/x/g; return $s
}
while (1) {
if (/(?<= )(\d+(\.\d*)?|\.\d+)(?= )/) {
print $`.f($&); s/^$`$&//
} else {
print; last
}
}

The RE does not use up the 2 spaces (using look-behind & look-ahead
matching).
Also I treat .67 as a valid number.

echo " 12.3 45 a1b2 foo12 3.4 89 1.6.7 " | PERL -n conv.pl
xx.x 45 a1b2 foo12 3.4 xx 1.6.7

echo " 12.3 45 a1b2 foo12 3.4 89 .67 " | PERL -n conv.pl
xx.x 45 a1b2 foo12 3.4 xx .xx

James

dan.rickhoff@comcast.net

2005-11-22, 8:53 pm

RolandRB,

RolandRB wrote:
> How do I convert digits to "x"s when they have two spaces in front and
> two spaces at back (or I don't want them converted) and ...
> ... (underscore character denotes space)


Please clarify your requirements, should
__123__34__
convert to
__xxx__34__
or to
__123__xx__

Also, what do you mean by "or I don't want them converted"?

Thanks
Dan R.

StrangeRover@gmail.com

2005-11-23, 7:51 am

sed -e 's/[0-9]/x/g'

RolandRB

2005-11-23, 7:51 am


StrangeRover@gmail.com wrote:
> sed -e 's/[0-9]/x/g'


I think the original idea has been lost but thanks anyway. I don't want
to convert all the digits into x's. Only when it appears in certain
ways.

Thanks for all the responses from everyone in this thread. I couldn't
make sense of most of it so I went for an ugly solution. It appears to
be buggy but it does its job well enough. It doesn't have to be
perfect.


sed -e 's%[0-9][0-9][A-Z][A-Z][A-Z][0-9][0-9][0-9][0-9]%xxMTH20xx%g' \
-e 's%[0-9][0-9][A-Z][A-Z][A-Z][0-9][0-9]%xxMTHxx%g' \
-e 's%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%xx/xx/xxxx%g' \
-e 's%[0-9][0-9]/[0-9][0-9]/[0-9][0-9]%xx/xx/xx%g' \
-e 's%(N=[0-9][0-9][0-9][0-9])%(N=xxxx)%g' \
-e 's%(N=[0-9][0-9][0-9])%(N=xxx)%g' \
-e 's%(N=[0-9][0-9])%(N=xx)%g' \
-e 's%(N=[0-9])%(N=x)%g' \
-e 's% ..[0-9][0-9] (..[0-9]\.[0-9]) [0-9].. % xxx ( xx.x) xxx %g' \
-e 's% [0-9][0-9]/[0-9][0-9] ( .[0-9]\.[0-9])% xx/xx ( xx.x)%g' \
-e 's% [0-9]/[0-9][0-9] ( .[0-9]\.[0-9])% x/xx ( xx.x)%g' \
-e 's% .[0-9][0-9] (..[0-9]\.[0-9])% xxx ( xx.x)%g' \
-e 's% .[0-9] (..[0-9]\.[0-9])% xx ( xx.x)%g' \
-e 's% [0-9][0-9][0-9][0-9][0-9]\.[0-9] % xxxxx.x %g' \
-e 's% [0-9][0-9][0-9][0-9]\.[0-9][0-9] % xxxx.xx %g' \
-e 's% [0-9][0-9][0-9][0-9]\.[0-9] % xxxx.x %g' \
-e 's% [0-9][0-9][0-9]\.[0-9][0-9] % xxx.xx %g' \
-e 's% [0-9][0-9][0-9]\.[0-9] % xxx.x %g' \
-e 's% [0-9][0-9]\.[0-9][0-9] % xx.xx %g' \
-e 's% [0-9]\.[0-9][0-9] % x.xx %g' \
-e 's% [0-9][0-9]\.[0-9] % xx.x %g' \
-e 's% [0-9]\.[0-9] % x.x %g' \
-e 's% [0-9][0-9][0-9][0-9][0-9] % xxxxx %g' \
-e 's% [0-9][0-9][0-9][0-9][0-9] % xxxxx %g' \
-e 's% [0-9][0-9][0-9][0-9] % xxxx %g' \
-e 's% [0-9][0-9][0-9] % xxx %g' \
-e 's% [0-9][0-9] % xx %g' \
-e 's% [0-9][0-9][0-9]\.[0-9][0-9][0-9][0-9]% xxx.xxxx%g' \
-e 's% [0-9][0-9]\.[0-9][0-9][0-9][0-9]% xx.xxxx%g' \
-e 's% [0-9]\.[0-9][0-9][0-9][0-9]% x.xxxx%g' \
-e 's% [0-9][0-9][0-9]\.[0-9][0-9][0-9]% xxx.xxx%g' \
-e 's% [0-9][0-9]\.[0-9][0-9][0-9]% xx.xxx%g' \
-e 's% [0-9]\.[0-9][0-9][0-9]% x.xxx%g' \
-e 's% [0-9][0-9][0-9]\.[0-9][0-9]$% xxx.xx%g' \
-e 's% [0-9][0-9]\.[0-9][0-9]$% xx.xx%g' \
-e 's% [0-9]\.[0-9][0-9]$% x.xx%g' \
-e 's% [0-9][0-9][0-9][0-9]\.[0-9]$% xxxx.x%g' \
-e 's% [0-9][0-9][0-9]\.[0-9]$% xxx.x%g' \
-e 's% [0-9][0-9]\.[0-9]$% xx.x%g' \
-e 's% [0-9]\.[0-9]$% x.x%g' \
-e 's% [0-9][0-9][0-9][0-9][0-9]$% xxxxx%g' \
-e 's% [0-9][0-9][0-9][0-9]$% xxxx%g' \
-e 's% [0-9][0-9][0-9]$% xxx%g' \
-e 's% [0-9][0-9]$% xx%g' \
-e 's% 0\.[0-9][0-9]% x.xx%g' \
-e 's%-0\.[0-9][0-9][0-9]%-x.xxx%g' \
-e 's%(0\.[0-9][0-9][0-9]%(x.xxx%g' \
-e 's% [0-9] % x %g' $1

dan.rickhoff@comcast.net

2005-11-23, 5:54 pm


I assumed that the following lines (but with spaces instead of commas):

8989,,123,,z8z,,134.5,,123,,
,,000,,
-u2 -z
*,,123,,*
#,,456,,#
\n,,789,,\n
,,..12,,
,,3..4,,
,,56..,,
,,.,,
,,.123,,, ,,1.23,, ,,123.,, ,,123,,
,,123,,, ,,123.,, ,,1.23,, ,,.123,,

should convert (but with spaces instead of commas) to

8989,,xxx,,z8z,,xxx.x,,123,,
,,xxx,,
-u2 -z
*,,xxx,,*
#,,xxx,,#
\n,,xxx,,\n
,,..12,,
,,3..4,,
,,56..,,
,,.,,
,,.xxx,,, ,,x.xx,, ,,xxx.,, ,,xxx,,
,,xxx,,, ,,xxx.,, ,,x.xx,, ,,.xxx,,

Rather than restricting myself to sed, as the original poster had
suggested,, I restricted myself to using **only** ksh built-ins (i.e.,
no sed, awk, perl, tr, ...). Unfortunately, my solution swelled to 66
lines of code, so I decided not to include it here. I can email it
directly to anyone who wants it.

Regards,
Dan R.

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com