Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Multiline Hash - how to get rid of formatting?

by klassisc (Initiate)
on Apr 30, 2012 at 07:03 UTC ( #968012=perlquestion: print w/ replies, xml ) Need Help??
klassisc has asked for the wisdom of the Perl Monks concerning the following question:

Hi, nice website :-) I'm pretty new to Perl and I've got the following question. I create an array of hashes with values as follows:
my @Workflow = ( {Body => "1. Blah 2. Blubb 3. more blah", },[...]
Now this returns me (in a mod_perl environment) formatted text. Can I get rid of this? A workaround would probably be to use the following with \n, I don't want to use this...
my @Workflow = ( {Body => "1. Blah\n" . "2. Blubb\n" . "3. more blah", },[...]
Anyway is there a kind of flag which supresses the formatting in the first case? And why don't the following work? I tried to get rid of the spaces afterwards...
$Workflow[$i]{Body} =~ s/^\s+//m; $Workflow[$i]{Body} =~ s/\s{2,}//; $Workflow[$i]{Body} =~ s/ {2,}//;
It's strange. The last one returns, in a 4 line value, the first 2 lines cleaned up from leading spaces, 3rd and 4th line untouched. TIA Michael

Comment on Multiline Hash - how to get rid of formatting?
Select or Download Code
Replies are listed 'Best First'.
Re: Multiline Hash - how to get rid of formatting?
by Anonymous Monk on Apr 30, 2012 at 07:36 UTC

    Now this returns me (in a mod_perl environment) formatted text. Can I get rid of this?

    Are you surprised this includes white-space?

    my $foo = "1. Blah 2. Blubb 3. more blah";

    use Data::Dump; dd $foo; __END__ "1. Blah\n 2. Blubb\n 3. more blah"

    That is how strings work :) See perlintro

    And why don't the following work?

    A couple of reasons, do this instead

    $Workflow[$i]{Body} =~ s/^\s+//mg; # g means global
Re: Multiline Hash - how to get rid of formatting?
by tospo (Hermit) on Apr 30, 2012 at 07:49 UTC

    What do you mean with "formatted text"? That you get a lot of spaces? That's because you have those spaces in your string values for 'body'. If you want a newline you must use \n as in your second example, Perl doesn't care about newlines you used to format the script in which you defined the data structure.

    But there are some other issues here:

    • your array seems to contain hashes with a single key ('Body'). If there are no other keys then you don't want an array of hashes, you want an array of arrays but maybe that's just the case in your short exapmle here? Is it possible that 'Body' is the name of a workflow? In that case you want a hash of arrays
    • you probably don't want the formatting ()newlines, spaces) in your strings at all. A data structure should store data. formatting should be done at the point of consumption of the data structure. For exmaple: if you need to print the data structure as a list in HTML you want to wrap each element in list tags. If you want to dump it to the command line, you want to add newlines at the end of each string. Try to separate data from presentation. Feel free to ask if you need more details about this.
    • the actual strings ("1. Blah..") you are storing there represent an ordered list, therefore you should store them as an array, not one long string as you do now.
    • In short, I think this is what you should have:

      my %workflows = ( 'workflow1' => [ "first step", "second step", "third step" ], 'workflow2' => [ "first step", "second step", "third step" ], );
      Print a workflow to the command line:
      print "Workflow1 is:\n" . join("\n", @%{$workflows{'workflow1'}})."\n" +;
      I hope that helps to get you started - welcome to Perl!

        hmmm, I must admit that I learned something today: after many years of working with Perl I never knew that newlines from your source code are preserved in double-qouted strings but it seems they really are.
        OK, forget the bit about HAVING to put the \n in your strings although I would still advice to do that if you want nelines because it is a nightmare having to figure out how where the spaces end and where there is an actual newline when editing your code.
        However, the main point of my reply remains valid: don't try to stuff formatting into your data structure unless you really have to. Format the data as and when you need to print it and store it as pure data. I also think that it is true that the OP hasn't got the right data structure yet to present his data.
Re: Multiline Hash - how to get rid of formatting?
by tobyink (Abbot) on Apr 30, 2012 at 07:34 UTC

    Syntax::Feature::Ql is close to what you want. It gives you a quote-like operator ql such that:

    use syntax 'ql'; use Test::More tests => 1; my $greeting = ql{ Hello World }; is($greeting, q{Hello World});

    Following the same technique you could create a quote-like operator which trims whitespace from the start of each line but preserves line breaks.

    If you're happy just to adjust the string with a regular expression though, you're probably looking for:

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      This is quite cute...

      use 5.010; use strict; QTRIM_SETUP: { my $trimmer; BEGIN { $trimmer = sub ($) { @_ = map { s/(^\s+)|(\s+$)//g; $_ } split /\n/, shift; shift until length $_[0]; pop until length $_[-1]; join "\n", @_; } } use PerlX::QuoteOperator qtrim => { -emulate => 'q', -with => $t +rimmer }; use PerlX::QuoteOperator qqtrim => { -emulate => 'qq', -with => $t +rimmer }; } my $string = qtrim{ Hello World }; say "[$string]";

      Obviously, if you were doing this in "real life" you'd move the QTRIM_SETUP block into a module, so that you could just do:

      use 5.010; use strict; use PerlX::Qtrim; my $string = qtrim{ Hello World }; say "[$string]";

      There's a slight annoyance with qqtrim in that this:

      my $embedded = "\n \n"; my $multiline = qqtrim{ Hello $embedded World };

      ... will also end up stripping the spaces in $embedded which is somewhat counter-intuitive.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      sorry, but I think this will set the OP off on the wrong trajectory. I think the problem is confusion about the usage of data structures and formatting in script files vs. formatting that Perl sees.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://968012]
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2016-05-01 07:43 GMT
Find Nodes?
    Voting Booth?

    No recent polls found