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

Data is entered to a form in three fields, passed to a perl script that saves the fields to a file with a bar | separating the fields. Each form data is in a separate file. At times this data may need to be updated or changed in some way. I have a perl script that uses split to separate the fields and creates a form for data maintenance. My problem is that the fields may contain a carriage and/or line feed and when this happens the next line goes back to the first array element. How can I display the data as originally entered with cr and lf. Any help would be appreciated. Thanks , Simon

Replies are listed 'Best First'.
Re: changing data in a file
by benn (Vicar) on Apr 20, 2003 at 09:30 UTC
    It *sounds* like you're wrting out to a text file then reading it back in again line-by-line. Obviously, if you save out a CR/LF in the middle of some data, this will constitute an end-of-line marker for your 'read' script, splitting your line into two.

    Therefore, you probably need to 'escape' \r and \n and then unescape them when you read them back. A common trick, if you are using HTML to display your data, is using something like s/[\r\n]/<br>/g - this will replace all CR/LF with <br> tags. If you want them displayed back as carriage returns, then your 'read' script simply reverses the transformation.

    Another common way is to replace with the *string* "\n" (s/\n\/\\n/g;) which again you transform back (s/\\n/\n/g;) when you read it in.

    Cheers,
    Ben.
      s/\\n/\n/g;

      You've broken the solution by creating it: I might have had a plaintext \n in the text before, that now becomes a newline. Oops.

      If you escape any characters, you need to escape the escape character as well:

      s/\\/\\s/g; s/\n/\\n/g; s/\r/\\r/g;
      so that a plaintext \n becomes \sn, which won't be matched by the regex that unescapes newlines. Then you can do the same thing backwards:
      s/\\n/\n/g; s/\\r/\r/g; s/\\s/\\/g;
      Just don't forget to leave the last unescaping last. If the escape code for the character is itself (ie s/\\/\\\\/g;), then unescaping becomes much more complicated, because you could match a \n that's actually part of a sequence like \\n. So you'll have to unwrap the string very carefully:
      my %xlat = ('\\' => "\\", 'n' => "\n", 'r' => "\r"); s/\G(?:\\(.)|(.))/defined($1) ? $xlat{$1} : $2/eg;

      And I haven't tested this, so I'm not even sure I got it right on the first try.

      Quoting and escaping are hair-raisingly complex issues - be careful.

      I have discovered that there are two types of command interfaces in the world of computing:
      good interfaces and user interfaces.

      — Dan J. Bernstein, The qmail security guarantee

      Makeshifts last the longest.

      Ben, Thanks for the great help. You understood my problem and I took your advice of substituting a <br> for the CR/LF and have the script working. Many thanks, Simon

      2003-04-20 edit ybiC: HTML encoding for <br>

        My pleasure - and welcome to the monastery, btw. A couple of minor points that might also help - you need to use &lt; and &gt; in order to display an html tag, like that <br> there...and don't fret about Abigail-II's 'express yourself properly boy!' answer - you got off lightly. :) Do have a wander around the halls though and check out the PerlMonks FAQ section on effective questioning - the hardest thing to do here is have to parse a question before being able to understand / answer it :).

        cheers
        Ben
Re: changing data in a file
by Abigail-II (Bishop) on Apr 20, 2003 at 00:39 UTC
    Your question isn't clear, and there's no code. You say data from each form gets put into a separate file, and the fields are separated by vertical bars. So, newlines or carriage returns have no special meaning - only the vertical bars do.

    Then you describe a problem concerning newlines and carriage returns. Obviously, you are treating newlines and carriage returns differently than the letter h or the period.

    However, you don't tell us how, nor do you show us code. I refuse to make guesses of what you can do wrong. Formulate your question better.

    Abigail

      Abigail, Thanks for taking the time to respond to my question. I know the question showed no code and I can understand your refusal to "make guesses". However, I was lucky in that another person saw the question and understood completely what my problem was. His solution, like my question , was brief and to the point. I've followed his suggestion and have my script working perfectly. Thanks again, Simon
      Why do you have to belittle the person? If you can't answer their question with the information available, either ignore it or ask for more information. Skip the snide comments. Elitist attitudes like yours scare people away. Maybe you like that, but I don't think other people do. This place often gets a bad rap for not being friendly. Can you guess why?

      You provide good information, but could you put down the attitude and try to be a nice person?
        At least I sign my posting with a recognizable name. How many years of answering questions in Perl forums do you have? If you don't like me, don't read my posting; they are easy to recognize as they aren't posted by a shared account.

        Abigail