Before I tell you what you need to do right, let's look at what you're doing wrong:
$char =~ s/.|$/|/g;
The problem here is that both .
and |
are metacharacters in regular expressions. The |
means "or", so you're saying "match .
or $
". You correctly know that $
means the end of the string, but .
means "any one character." So it immediately matches one character, and continues to immediately match one character, each time changing that character to |
(metacharacters don't apply in the second half of the s///
expression), then it matches the end of the string and adds a |
in there. Or something like that. Basically, not what you want to happen.
$char =~ s/[.|]$/|/g;
Well, inside []
s, .
and |
stop being metacharacters, but []
means "one of these," so this regular expression looks for the character before the end of the string, and if it's either |
or .
, it changes it to |
. Again, not what you want to happen.
$char = tr/.|//d; # and later add |.
tr
is the wrong tool for this job. This would delete all .
and |
characters in your string, expect that you're not using the =~
regex match operator, but the =
assignment operator. Definitely not what you want to happen.
What you want is this:
$char =~ s/\.\|$/|/;
We've escaped both the .
and the |
with a \
so Perl knows "the character after the \
is a literal character with no special meaning*" and matches a literal .|
at the end of your string and replaces it with just |
.
That said, it sounds like you're kind of new to regular expressions. I'm a big fan of perldoc perlretut
, which I think is one of the best (if not the best) introduction to regular expressions in Perl. You should really read it - regexes are a powerful tool in the hands of those who know them, and a powerful headache to those who don't.