Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

replacing pipe "|"

by nadadogg (Acolyte)
on Mar 26, 2003 at 20:30 UTC ( [id://246070]=perlquestion: print w/replies, xml ) Need Help??

nadadogg has asked for the wisdom of the Perl Monks concerning the following question:

I am having to replace the pipe character with a space in every instance it occurs in a file so that I can manipulate it using other 3rd party programs. This is my code, and it has worked in several other places where I've had to replace characters, but replacing the pipe makes it insert a space after every single character
sub fixspace{ $rem ="|"; $rep = " "; open FILE, "<$file"; open OUTP, ">c:\\joshperl\\deptemp.txt"; while (<FILE>) { s/$rem/$rep/go; print OUTP; } close FILE; close OUTP; }
my data looks like this originally
|03/17/03|2314|0x53('S')|03/17/03|03/19/03|0.00|0.00|133712.00|133712.00|123456433|431234533|412345901|82|3.00| and comes out like this
| 0 3 / 1 4 / 0 3 | 2 2 0 7 | 0 x 4 E ( ' N ' ) | 0 3 / 1 7 / 0 3 | 0 3 / 1 7 / 0 3 | 0 . 0 0 | 0 . 0 0 | 8 0 3 6 0 . 0 0 | 8 0 3 6 0 . 0 0 | 1 3 4 5 6 7 8 9 9 | 3 4 5 6 7 7 7 5 8 | 3 4 5 6 7 9 6 6 3 | 9 1 | 1 . 0 0 |

Don't worry about the values of the fields, I had to pull from different files and mess with the numbers to keep all our info locked away in a vault somewhere.

Replies are listed 'Best First'.
Re: replacing pipe "|"
by SarahM (Monk) on Mar 26, 2003 at 20:38 UTC
    That's because the | is a special character, and you need to escape it. change $rem ="|"; to $rem ="\\|"; and it'll work. Another (cleaner/easier) option is to use \Q and \E (they escape the characters for you). So change s/$rem/$rep/go; to s/\Q$rem\E/$rep/go;
      Thank you very much guys, and gals, SarahM's answer worked perfectly the first time through, and now maybe ill meet my deadlines :)
Re: replacing pipe "|"
by BrowserUk (Patriarch) on Mar 26, 2003 at 20:38 UTC

    The pipe | char is a regex meta character and therefore needs to be escaped if you want to use it as a literal.

    Substituing the following for the equivalent line of your script should solve the problem

    s/\Q$rem\E/$rep/go;

    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: replacing pipe "|"
by pfaut (Priest) on Mar 26, 2003 at 20:41 UTC

    The pipe character (|) means alternation inside a regex. It needs to be escaped. Try s/\Q$rem\E/$rep/g.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
Re: replacing pipe "|"
by Util (Priest) on Mar 26, 2003 at 22:22 UTC

    When you want to replace all occurrences of a single character with a different single character, use tr/// instead of s///g. It is faster, and you won't ever be bitten by the meta-character problem, because tr/// does not respect meta-characters (no interpolation). Your documentative use of $rem and $rep would need to be replaced by a comment, of course.

    # Translate all '|' (pipe) characters into ' ' (spaces). while (<FILE>) { tr/|/ /; print OUTP; }

    tr/// is in the perlop manpage. It does a lot more that just single/single transliteration, but this is where tr/// and s/// overlap in function.

    FYI, you can do the equivalent under Windows with this one-liner:
    perl -pe "tr/|/ /" filename > c:\joshperl\deptemp.txt

      If it was *always* singles, i would do that, but occasionally i have to change sections. With this one, it is predominantly single-char. Thanks again people
Re: replacing pipe "|"
by thpfft (Chaplain) on Mar 26, 2003 at 20:45 UTC

    you need to escape the pipe, which sounds a lot more exciting than it is:

    s/\|/ /go;

    will work. | is a control character in a regex, unless preceded by the escaping backslash.

    update goodness. that's a new peak of redundancy. I was too busy wondering why s// /g does what it does. Can anyone explain?

    tachyon yeah, it's the op's /o, and i forgot to take it out when i simplified the reply.

      You do know that /o tells perl that any $scalar_var in the regex will never change its value so only compile the regex once don't you? If so why use it whan all you have is literals in your example?

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      s// /g replaces all null characters with a space. And it so happens that a null character is between every other character, so...

      And by the way, s/|/ /g means replace either null or null with a space. :)

      Does this answer your question?

      Update: The 'null character' terminology isn't correct. See BrowerUK's note.

        not really, but it restates it nicely enough. it's the so-happens part which intrigues me. why is there a null character there, and why only one?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://246070]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (2)
As of 2024-04-25 20:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found