Perl Regex Question: how to translate only the leading letters of a line

Y

Yu

Hi,
I wonder if there is an elegant way of converting
number 1-9 into letter A-I for the LEADING letter
of a line. For example:

Input:
1 xxxx1234....

Ouput:
A xxxx1234....

The tr operator does not take the special position
character such as '^' and '$', so it would operate
on every match in the input line. Any input will
greatly appreciated.

-Yu
 
A

A. Sinan Unur

(e-mail address removed) (Yu) wrote in @posting.google.com:
Hi,
I wonder if there is an elegant way of converting
number 1-9 into letter A-I for the LEADING letter
of a line. For example:

Input:
1 xxxx1234....

Ouput:
A xxxx1234....

The tr operator does not take the special position
character such as '^' and '$', so it would operate
on every match in the input line.

What is preventing you from using s/// then?

#! perl

use strict;
use warnings;

my @repl = ('A' .. 'I');

while(<DATA>) {
s/^([1-9]) /$repl[$1-1] /;
print;
}

__DATA__
1 xxxx1234....
2 xxxx1234....
3 xxxx1234....
4 xxxx1234....
5 xxxx1234....
6 xxxx1234....
1other kind of line
7 xxxx1234....
8 xxxx1234....
9 xxxx1234....
0 xxxx1234....
0 xxxx1234....
3 xxxx1234....
5 xxxx1234....
6 xxxx1234....
7 xxxx1234....
 
G

Gunnar Hjalmarsson

Yu said:
I wonder if there is an elegant way of converting number 1-9 into
letter A-I for the LEADING letter of a line. For example:

Input:
1 xxxx1234....

Ouput:
A xxxx1234....

The tr operator does not take the special position character such
as '^' and '$', so it would operate on every match in the input
line.

substr($line, 0, 1) =~ tr/1-9/A-I/;
 
A

A. Sinan Unur

....

Interesting hack, yes? I am fascinated by how tr keeps
track of numerical position for the right hand side.

tr does not keep track of anything. substr produces an lvalue.

Based on the OP's example, I concluded that the requirement was to
replace a digit followed by a space with the corresponding letter
followed by a space at the beginning of the line. Therefore, I did not
suggest the tr solution.
 
J

Jay Tilton

(e-mail address removed) (Yu) wrote:

: I wonder if there is an elegant way of converting
: number 1-9 into letter A-I for the LEADING letter
: of a line. For example:
:
: Input:
: 1 xxxx1234....
:
: Ouput:
: A xxxx1234....

$_ ^= 'p';
 
G

Gunnar Hjalmarsson

Purl said:
Interesting hack, yes? I am fascinated by how tr keeps track of
numerical position for the right hand side.

However, I have been told many times using Perl hacks is bad, bad,
BAD!

It's not a hack. According to "perldoc -f substr", substr() can be
used as an lvalue, so it's documented behaviour.
 
J

Jay Tilton

: Purl Gurl wrote:
:
: > Gunnar Hjalmarsson wrote:
: > > Yu wrote:
:
: > > > The tr operator does not take the special position character such
:
: > > substr($line, 0, 1) =~ tr/1-9/A-I/;
:
: > Copy cat. * meows *
:
: > Interesting hack, yes? I am fascinated by how tr keeps
: > track of numerical position for the right hand side.
:
:
: Here is another variation which is most interesting,
:
: $string = "abcdefghi123456789";
:
: $string =~ tr/1-9/A-I/;
:
: print $string;
:
: --
:
: abcdefghiABCDEFGHI

[truncated]

What intersting thing, other than the documented behavior of the tr///
operator, were these samples meant to demonstrate?
 
G

Gunnar Hjalmarsson

Jay said:
$_ ^= 'p';

Hmm ... I know what $_ is. Would you mind explaining ^= and 'p'? Are
they explained in the Perl docs, or are they C things that happen to
work in Perl as well?
 
A

A. Sinan Unur

I am referencing the behavior of transliteration which
behaves in a way which is not intuitive. You would not
expect numbers to be translated to letters according to
numerical value.

That is not what is happening. You are confused.
You would expect numbers to be translated according to
sequential position.

See:

#! perl

use strict;
use warnings;

while(<DATA>) {
substr($_, 0, 1) =~ tr/324568791/A-I/;
print;
}

__DATA__
1 xxxx1234....
2 xxxx1234....
3 xxxx1234....
4 xxxx1234....
5 xxxx1234....
6 xxxx1234....
7 xxxx1234....
8 xxxx1234....
9 xxxx1234....

C:\Develop\perl> t
I xxxx1234....
B xxxx1234....
A xxxx1234....
C xxxx1234....
D xxxx1234....
E xxxx1234....
G xxxx1234....
F xxxx1234....
H xxxx1234....
 
G

Gunnar Hjalmarsson

Purl said:
I am referencing the behavior of transliteration which behaves in a
way which is not intuitive. You would not expect numbers to be
translated to letters according to numerical value. You would
expect numbers to be translated according to sequential position.

I'm not following you. tr/// translates characters irrespective of
their numerical values.

$_ = "8uesti65i5g\n";
tr/5-8/n-q/;
print;

Outputs:
questioning
You have an Einstien quote on your homepage. Review it.

Do you mean:

"The important thing is never to stop questioning."

I agree that's wise, but please don't overdo it. :)
 
G

Gunnar Hjalmarsson

Purl said:
Review my examples, which another used as an excuse to troll,
specifically translation of odd numbers, even numbers, into equal
odd numbered and even numbered letters.

Numbers are translated into letters according to numerical value,
not sequential position in a string.

You are jumping at conclusions out from an illusory causality. None of
the posted examples shows anything but the documented behaviour of the
tr/// operator.
 
A

A. Sinan Unur

$string = "131313131";

$string =~ tr/1-9/A-I/;

print $string;

ACACACACA


Gunnar, it is not documented behavior to which I refer. That
is common knowledge. No problem.
....

For my example up there, logically you would expect,

ABCDEFGHI

That is not logical at all.

tr/1-9/A-I/;

means

'1' maps to 'A'
'2' maps to 'B'
'3' maps to 'C'
'4' maps to 'D'
'5' maps to 'E'
'6' maps to 'F'
'7' maps to 'G'
'8' maps to 'H'
'9' maps to 'I'

It does not mean 1st character maps to 'A', 2nd character maps to 'B' so
on and so forth.

Can you imagine how hard it would be to use the tr operator if the latter
were the case?
 
B

Bob Walton

Gunnar said:
Hmm ... I know what $_ is. Would you mind explaining ^= and 'p'? Are
they explained in the Perl docs, or are they C things that happen to
work in Perl as well?

Well, $_ ^= 'p'; does $_ xor 'p' (xor being "bitwise exclusive or" of
two character strings), and puts the result back in $_. It appears that
the binary representation of 'p' (on ASCII machines, anyway) is the
correct value to convert via xor the binary representation of '1'
through '9' to that of 'A' through 'I'. That probably won't fly on a
platform which uses a non-ASCII character set.
 
G

Gunnar Hjalmarsson

Purl said:
$string = "131313131";

$string =~ tr/1-9/A-I/;

print $string;

--

ACACACACA


For my example up there, logically you would expect,

ABCDEFGHI

That is intuitive, logical.

I simply don't agree. To me, that's neither more intuitive nor more
logical that how tr/// behaves. It's another thing, which using Perl
can be written e.g. as:

my @letters = 'A'..'I';
$string =~ s/\d/shift @letters/eg;
You expect processing to occur in string position order, not
according to numerical value.

I don't understand why you keep talking about "numerical value". Each
found character in $string that is represented in the search list is
replaced with a specific character in the replacement list. It has
nothing to do with which value respective character would return when
used in a numerical context.
 
J

Joe Smith

Purl said:
$string = "131313131";

$string =~ tr/1-9/A-I/;

print $string;

The perl statement
tr/3/C/;
clearly will translate all occurrances of "3" to "C",
regardless of where the characters appear in the string.

The perl statement
tr/1/A/;
clearly will translate all occurances of "1" to "A",
regardless of where they characters appear in the string.

For the perl statement
tr/31/CA/;
two translations occur. All occurances of "1" get translated
to "A", not just the ones that immediately follow a "3"
(which is what the s/// operator would do).

For
tr/123456789/ABCDEFGHI/;
all occurrances of "2" get translated to "B", regardless of
whether they follow a "1" or preceed "3" or not.

If we can agree on that, then there should not be any problem
in understanding that
tr/123456789/ABCDEFGHI/;
and
tr/1-9/A-I/;
are identical (based on how "-" is interpeted by the tr/// function.
You expect processing to
occur in string position order, not according to
numerical value.

That is both correct and incorrect.
/1-9/ is the string of all the characters whose ASCII codes range from
31 to 39 decimal ("123456789").
/A-I/ is the string of all the characters whose ASCII codes range from
65 to 73 decimal ("ABCDEFGHI").
So the string position order in these examples is based on the numerical
value of the character's ASCII code. This is true for both digit and
non-digit characters.

The tr/// function is documented to work in string position order.
That makes it very handy to use in performing ROT13 encoding.

tr/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm/;
is the same as tr/A-MN-Za-mn-z/N-ZA-Mn-za-m/;
and is the same as tr/A-Za-z/N-ZA-Mn-za-m/;.
The latter two use sequences of start_character, hyphen, end_character to
indicate consecutive characters in the ASCII code. All three of them
translate one set of 52 characters to a different set of 52 characters.

Since tr/// does work in string position order, you would expect
tr/369258147/CFIBEHADG/;
to operate exactly the same was as
tr/123456789/ABCDEFGHI/;
and it does.

-Joe
 
J

Joe Smith

Purl said:
However, for 3 to translate to C regardless of string
occurance position, is illogical

But it does match the very reason why tr was created.
It was designed to perform a specific function, which it does.
It is quite logical for people who recognize what such a
function would be good for.
-Joe
 
H

Henry Law

You ruin any enjoyment for those reading here, who
are here to learn more about Perl. You ruin any
enjoyment for those here wanting to discuss and
share Perl in a friendly fun manner.

Oh that's rich, coming from Pearl Girl. I had PG's posts in the "mark
read already" category, just in case there might be something in one
of them one day that actually was useful - because it's apparent that
there's a brain in there somewhere and it probably knows a lot. But
my hopes have proved groundless: every thread in which the Pearly
Queen joins tends inexorably towards nonsense; so I have to upgrade
her/him/it to the "delete unread" category.

.... but I wish the rest of you - the people who really do provide
useful information - would just stop posting altogether when the
Nacreous One joins a thread.

Henry Law <>< Manchester, England
 
G

Gunnar Hjalmarsson

Henry said:
... but I wish the rest of you - the people who really do provide
useful information - would just stop posting altogether when the
Nacreous One joins a thread.

So, you are suggesting that every such discussion would cease
abruptly, whether on topic or not???

To me, the obvious key to a less noisy newsgroup is: Keep your
postings on topic!
 
J

Jay Tilton

: Jay Tilton elected to troll:
:
: > Purl Gurl wrote:
: > : Purl Gurl wrote:
: > : > Gunnar Hjalmarsson wrote:
: > : > > Yu wrote:
:
: > What intersting thing, other than the documented behavior of the tr///
: > operator, were these samples meant to demonstrate?
:
: Clearly my examples demonstrate you boys will use
: any excuse to troll, no matter how lame of an excuse.

*sigh*

I asked the question poorly.

I saw a mundane use of the tr/// operator. You evidently saw something
remarkable. I wanted to know how its behavior differed from what you
expected it to do.

The question has been answered in a different segment of this thread now.

: Annoying boys like you work hard at creating an
: atmosphere of discontent and hatred in this group.

I acknowledge the futility in trying to dissuade you from believing that.

: You ruin any enjoyment for those reading here, who
: are here to learn more about Perl. You ruin any
: enjoyment for those here wanting to discuss and
: share Perl in a friendly fun manner.

An inference of malice is most often premised on faulty assumptions.
 
J

John W. Krahn

Yu said:
I wonder if there is an elegant way of converting
number 1-9 into letter A-I for the LEADING letter
of a line. For example:

Input:
1 xxxx1234....

Ouput:
A xxxx1234....

The tr operator does not take the special position
character such as '^' and '$', so it would operate
on every match in the input line. Any input will
greatly appreciated.

Here is one way to do it:

s/^([1-9])(?= xxxx1234)/qw(A B C D E F G H I)[$1-1]/e;


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top