FAQ
Hi,


I have to do a substitution of a pattern in a text file,

this pattern is a key of a hash table previously set.


so I want to replace my pattern by the corresponding value of the key
in the hash table


ex :

file : n1 n22

hash : n1 => wordA
n2 => wordB
n22 => wordN

I want to have filenew like this :

file : wordA wordN




with a single %s/pattern/hashpattern/g expression

Thanks for helping

Search Discussions

  • Brad Baxter at Jun 30, 2008 at 10:28 pm

    On Jun 30, 4:20 pm, callingel...@hotmail.fr (Epanda) wrote:
    Hi,

    I have to do a substitution of a pattern in a text file,
    So you know about perl -i, right?
    this pattern is a key of a hash table previously set.

    so I want to replace my pattern by the corresponding value of the key
    in the hash table

    ex :

    file : n1 n22

    hash : n1 => wordA
    n2 => wordB
    n22 => wordN

    I want to have filenew like this :

    file : wordA wordN

    with a single %s/pattern/hashpattern/g expression

    Thanks for helping
    You mean like this?

    perl -i.bak -pe '%h = (n1=>wordA, n22=>wordN); for $x (keys %h){ s/\Q
    $x/$h{$x}/g }' data.txt

    --
    Brad
  • Amit Saxena at Jul 1, 2008 at 8:29 am
    Why don't use perl "s" operator with "e" option ?

    $str =~ s/([^ ]+)/$hash{\1}/ge

    Regards,
    Amit Saxena
    On Tue, Jul 1, 2008 at 3:57 AM, Brad Baxter wrote:
    On Jun 30, 4:20 pm, callingel...@hotmail.fr (Epanda) wrote:
    Hi,

    I have to do a substitution of a pattern in a text file,
    So you know about perl -i, right?
    this pattern is a key of a hash table previously set.

    so I want to replace my pattern by the corresponding value of the key
    in the hash table

    ex :

    file : n1 n22

    hash : n1 => wordA
    n2 => wordB
    n22 => wordN

    I want to have filenew like this :

    file : wordA wordN

    with a single %s/pattern/hashpattern/g expression

    Thanks for helping
    You mean like this?

    perl -i.bak -pe '%h = (n1=>wordA, n22=>wordN); for $x (keys %h){ s/\Q
    $x/$h{$x}/g }' data.txt

    --
    Brad


    --
    To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/

  • John W. Krahn at Jul 1, 2008 at 10:49 am

    Amit Saxena wrote:
    Why don't use perl "s" operator with "e" option ?

    $str =~ s/([^ ]+)/$hash{\1}/ge
    You don't need the /e option to interpolate a variable in a double
    quoted string and you should use $1 instead of \1 inside a double quoted
    string:

    $str =~ s/([^ ]+)/$hash{$1}/g


    John
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall
  • Amit Saxena at Jul 1, 2008 at 1:01 pm
    Hi John,

    I am not only expanding a variable but also using that expanded variable as
    a key to ultimately find the value. That's why I need "e".

    Secondly, inside text that is to be substituted, I can use \1 as well. And
    moreover, for this, I don't need double quotes. If i purposefully
    incorporate double quotes, then I need $1.

    Regards,
    Amit Saxena
    On Tue, Jul 1, 2008 at 4:19 PM, John W. Krahn wrote:

    Amit Saxena wrote:
    Why don't use perl "s" operator with "e" option ?

    $str =~ s/([^ ]+)/$hash{\1}/ge
    You don't need the /e option to interpolate a variable in a double quoted
    string and you should use $1 instead of \1 inside a double quoted string:

    $str =~ s/([^ ]+)/$hash{$1}/g


    John
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall

    --
    To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/

  • Rob Dixon at Jul 1, 2008 at 2:15 pm

    Amit Saxena wrote:
    On Tue, Jul 1, 2008 at 4:19 PM, John W. Krahn wrote:

    Amit Saxena wrote:
    Why don't use perl "s" operator with "e" option ?

    $str =~ s/([^ ]+)/$hash{\1}/ge
    You don't need the /e option to interpolate a variable in a double quoted
    string and you should use $1 instead of \1 inside a double quoted string:

    $str =~ s/([^ ]+)/$hash{$1}/g
    I am not only expanding a variable but also using that expanded variable as
    a key to ultimately find the value. That's why I need "e".
    A single hash element is a scalar variable, and John is correct that you don't
    need the /e option to interpolate it if you key it properly with $1 instead of
    \1. Try it.
    Secondly, inside text that is to be substituted, I can use \1 as well. And
    moreover, for this, I don't need double quotes. If i purposefully
    incorporate double quotes, then I need $1.
    John's point wasn't that double-quotes were needed, but that right-hand side of
    a substitution behaves as a double-quoted string. I don't understand why you
    think you need $1 if you somehow involve double quotes explicitly.

    This is from

    perldoc perlre

    You would do well do read and understand it so that your advice on this group
    can agree with the documentation.
    Warning on \1 vs $1
    Some people get too used to writing things like:

    $pattern =~ s/(\W)/\\\1/g;

    This is grandfathered for the RHS of a substitute to avoid shocking the
    sed addicts, but it's a dirty habit to get into. That's because in
    PerlThink, the righthand side of an "s///" is a double-quoted string.
    "\1" in the usual double-quoted string means a control-A. The customary
    Unix meaning of "\1" is kludged in for "s///". However, if you get into
    the habit of doing that, you get yourself into trouble if you then add
    an "/e" modifier.

    s/(\d+)/ \1 + 1 /eg; # causes warning under -w

    Or if you try to do

    s/(\d+)/\1000/;

    You can't disambiguate that by saying "\{1}000", whereas you can fix it
    with "${1}000". The operation of interpolation should not be confused
    with the operation of matching a backreference. Certainly they mean two
    different things on the *left* side of the "s///".
    In addition,

    - The usual way of writing /([^ ]+)/ is /(\S+)/, and although the two are
    slightly different I doubt if you wanted your class to include tabs and
    formfeeds?

    - Your code will simply delete any word in the string that doesn't appear as a
    hash key, and will also throw warnings each time it does it.


    Rob
  • Rob Dixon at Jun 30, 2008 at 11:52 pm

    epanda wrote:

    I have to do a substitution of a pattern in a text file,

    this pattern is a key of a hash table previously set.


    so I want to replace my pattern by the corresponding value of the key
    in the hash table


    ex :

    file : n1 n22

    hash : n1 => wordA
    n2 => wordB
    n22 => wordN

    I want to have filenew like this :

    file : wordA wordN




    with a single %s/pattern/hashpattern/g expression
    Something like this maybe?

    HTH,

    Rob


    use strict;
    use warnings;

    my $str = 'n1 n22';

    my %hash = (
    n1 => 'wordA',
    n2 => 'wordB',
    n22 => 'wordN',
    );


    my $re = join '|', keys %hash;
    $re = qr/\b(?:$re)\b/o;

    $str =~ s/($re)/$hash{$1}/g;
    print $str;
  • Rob Dixon at Jul 1, 2008 at 5:47 pm

    nico io wrote:
    I have wrote this :
    s/(?<![0-9A-Za-z;])(\d+)(?!(\;\d+|\d+|\;\s+\d+\;\d+))/$hashTable{$1}/g

    it works but when a number is not as a key of the hash table it replace
    the numer by nothing.

    I would like to let the number if it doesn't belong to my hash table,
    how can I do ?
    Please keep your posts confined to the perl.beginners group so that others can
    both help and be helped by your questions.

    Please bottom-post your responses to the perl.beginners group so that extended
    threads remain comprehensible. Thank you.

    You should always put

    use strict;
    use warnings;

    at the start of your program, which would have given you a warning when missing
    keys were substituted.

    Your regex isn't clearly thought-out. For instance
    /(\d+)(?!(\;\d+|\d+|\;\s+\d+\;\d+)/ says that the string can't be followed by a
    semicolon and digits, or just digits, or a semicolon and whitespace and digits.
    Because (/d+) is greedy and will consume all the digits available there is no
    need to specify anything other than /(\d+)(?!;)/.

    You can stop missing keys being substituted by making your replacement string an
    expression. This should do what you want:

    $str =~ s/(?<![A-Z;])(\d+)(?!;)/ exists $hash{$1} ? $hash{$1} : $1 /gei;

    HTH,

    Rob
  • Epanda at Jul 1, 2008 at 6:54 pm
    this is not working

    here is an example of my file and I just want to replace with one
    regexp

    in file1 ddd ddd dddd by the value stored in my hash table
    in file2 all d
    in file3 not the first d; but all the others which is preceed by
    WORD;

    in all files
    not replacing block like that d;d;dd
    not replacing the 2 in WORD/WORD2;

    file1
    WORD/WORD2; d;d;dd; d;d;dd; d;d;d;
    d;d;d; ddd ddd ddd ddd dddd
    WORD/WORDWORD1/WORD1; d;d;dd; d;d;dd; d;d;d; d;d;d; ddd ddd
    ddd ddd ddddd

    file2
    WORD; d; dd; dd; dd; d; d; d; dd; dd; d; ddd; ddd; ddd;
    ddd; ddd; dddd;


    file3
    WORD/WORD1; d; d; ddd; dddd;


    Thanks Rob if you can help

    On 1 juil, 19:46, rob.di...@gmx.com (Rob Dixon) wrote:
    nico io wrote:
    I have wrote this :
    s/(?<![0-9A-Za-z;])(\d+)(?!(\;\d+|\d+|\;\s+\d+\;\d+))/$hashTable{$1}/g
    it works but when a number is not as a key of the hash table it replace
    the numer by nothing.
    I would like to let the number if it doesn't belong to my hash table,
    how can I do ?
    Please keep your posts confined to the perl.beginners group so that others can
    both help and be helped by your questions.

    Please bottom-post your responses to the perl.beginners group so that extended
    threads remain comprehensible. Thank you.

    You should always put

    use strict;
    use warnings;

    at the start of your program, which would have given you a warning when missing
    keys were substituted.

    Your regex isn't clearly thought-out. For instance
    /(\d+)(?!(\;\d+|\d+|\;\s+\d+\;\d+)/ says that the string can't be followed by a
    semicolon and digits, or just digits, or a semicolon and whitespace and digits.
    Because (/d+) is greedy and will consume all the digits available there is no
    need to specify anything other than /(\d+)(?!;)/.

    You can stop missing keys being substituted by making your replacement string an
    expression. This should do what you want:

    $str =~ s/(?<![A-Z;])(\d+)(?!;)/ exists $hash{$1} ? $hash{$1} : $1 /gei;

    HTH,

    Rob
  • Rob Dixon at Jul 1, 2008 at 7:35 pm

    epanda wrote:
    this is not working

    here is an example of my file and I just want to replace with one
    regexp

    in file1 ddd ddd dddd by the value stored in my hash table
    in file2 all d
    in file3 not the first d; but all the others which is preceed by
    WORD;

    in all files
    not replacing block like that d;d;dd
    not replacing the 2 in WORD/WORD2;

    file1
    WORD/WORD2; d;d;dd; d;d;dd; d;d;d;
    d;d;d; ddd ddd ddd ddd dddd
    WORD/WORDWORD1/WORD1; d;d;dd; d;d;dd; d;d;d; d;d;d; ddd ddd
    ddd ddd ddddd

    file2
    WORD; d; dd; dd; dd; d; d; d; dd; dd; d; ddd; ddd; ddd;
    ddd; ddd; dddd;


    file3
    WORD/WORD1; d; d; ddd; dddd;


    Thanks Rob if you can help
    I think you should post some real data so that we can see the difference between
    the fields you want translating. It's not clear, for instance, whether WORD is
    always the same word or if it can be used to determine the behaviour of the
    replacement.

    This seems to be close to what you need:

    s/ (?<!;) \b (\d+) (?!;\d) /exists $hash{$1} ? $hash{$1} : $1/exg;

    but I can't see how to distinguish the first d; in file3 to be left unmodified.

    Rob
  • Epanda at Jul 1, 2008 at 8:38 pm
    yes to distinguish in file3 the first d;, it is sufficient to avoid it
    by preceded WORD;\s+ \d+;

    but I have tried that and it is not working
    (?<!\w;|\w+;\s+)\b(\d+)(?!;\d|\d;\d;)

    On 1 juil, 21:34, rob.di...@gmx.com (Rob Dixon) wrote:
    epanda wrote:
    this is not working
    here is an example of my file and I just want to replace with one
    regexp
    in file1 ddd ddd dddd by the value stored in my hash table
    in file2 all d
    in file3 not the first d; but all the others      which is preceed by
    WORD;
    in all files
    not replacing block like that d;d;dd
    not replacing the 2 in WORD/WORD2;
    file1
    WORD/WORD2;                         d;d;dd;    d;d;dd;  d;d;d;
    d;d;d;   ddd  ddd  ddd  ddd  dddd
    WORD/WORDWORD1/WORD1;  d;d;dd;    d;d;dd;  d;d;d;  d;d;d;   ddd  ddd
    ddd  ddd  ddddd
    file2
    WORD;  d;  dd;  dd;  dd;  d;  d;  d;  dd;  dd;  d;  ddd;  ddd;  ddd;
    ddd;  ddd;  dddd;
    file3
    WORD/WORD1;  d;   d;  ddd;  dddd;
    Thanks Rob if you can help
    I think you should post some real data so that we can see the difference between
    the fields you want translating. It's not clear, for instance, whether WORD is
    always the same word or if it can be used to determine the behaviour of the
    replacement.

    This seems to be close to what you need:

    s/ (?<!;) \b (\d+) (?!;\d) /exists $hash{$1} ? $hash{$1} : $1/exg;

    but I can't see how to distinguish the first d; in file3 to be left unmodified.

    Rob
  • Dr.Ruud at Jul 2, 2008 at 6:32 pm

    epanda schreef:

    I want to replace my pattern by the corresponding value of the key
    in the hash table [...]
    with a single %s/pattern/hashpattern/g expression
    Why that last condition? Sounds like homework.
    And is unsound: often you want to do the longest possible change first.

    --
    Affijn, Ruud

    "Gewoon is een tijger."
  • Epanda at Jul 3, 2008 at 5:29 am
    It is ok I have found the good one substitution for me but I am
    amazing that perl is not as clever as vimscript regex in limitation of
    assertions.

    ex : perl is lost when I want to say that a digit has to not be
    preceed by this sentence :
    <aWord><aCharacter><aComma><aNumberOfUndefinedSpaces>
    /(?<!FRUIT.;\s*)\b(\d+)
    _______________________the pb is here
    On 2 juil, 20:30, rvtol+n...@isolution.nl (Dr.Ruud) wrote:
    epanda schreef:
    I want to replace my pattern by the corresponding value of the key
    in the hash table [...]
    with a single %s/pattern/hashpattern/g  expression
    Why that last condition? Sounds like homework.
    And is unsound: often you want to do the longest possible change first.

    --
    Affijn, Ruud

    "Gewoon is een tijger."
  • Dr.Ruud at Jul 4, 2008 at 10:21 am
    epanda schreef:

    Don't top post. Don't quote signatures and other trailers.
    rvtol:
    epanda:
    I want to replace my pattern by the corresponding value of the key
    in the hash table [...]
    with a single %s/pattern/hashpattern/g expression
    Why that last condition? Sounds like homework.
    And is unsound: often you want to do the longest possible change
    first.
    It is ok I have found the good one substitution for me but I am
    amazing that perl is not as clever as vimscript regex in limitation of
    assertions.
    Define "clever". I think you just need to look much more into the
    matter.

    ex : perl is lost when I want to say that a digit has to not be
    preceed by this sentence :
    <aWord><aCharacter><aComma><aNumberOfUndefinedSpaces>
    /(?<!FRUIT.;\s*)\b(\d+)
    _______________________the pb is here
    I don't see why you have a "\b" in there.

    Should "FRUIT." match patterns like "FRUITS" and "FRUITY"?

    First you say <aComma>, then you show a semicolon.

    Now come up with actual example where you had a problem with.

    --
    Affijn, Ruud

    "Gewoon is een tijger."

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedJun 30, '08 at 8:20p
activeJul 4, '08 at 10:21a
posts14
users6
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase