Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Search & Replace repeating characters

by g_speran (Scribe)
on Apr 22, 2020 at 22:24 UTC ( [id://11115909]=perlquestion: print w/replies, xml ) Need Help??

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

I am looking for a much easier way, if applicable, to do a search an replace on repeated characters. For example, my directory is "c:\\temp\\\\" (ending with 4 back slashes). I would like to do a search and replace that replaces multiple "/" or "\" with a single "/" and remove the trailing "/" if it exists. Below is the code i am currently using but i am sure there will be a much more elegant way of doing this
$ScriptDir="C:\\temp\\\\"; print "1. ${ScriptDir}\n"; $ScriptDir =~ s/\\+/\//g; print "2. ${ScriptDir}\n"; $ScriptDir =~ s/\/+/\//g; print "3. ${ScriptDir}\n"; if ($ScriptDir =~/$\//) {$ScriptDir=~ s/$\///;}

Replies are listed 'Best First'.
Re: Search & Replace repeating characters
by choroba (Cardinal) on Apr 22, 2020 at 22:36 UTC
    The most readable solution (at least for me) uses just two regexes, the first one shrinks the backslashes and replaces them with slahses, the second one removes the trailing slashes:
    my $script_dir = 'C:\\temp\\\\'; print "1. $script_dir\n"; $script_dir =~ s{\\+}{/}g; print "2. $script_dir\n"; $script_dir =~ s{/$}{}g; print "2. $script_dir\n";

    You can use transliteration with shrinking instead of substitution in the first step:

    $script_dir =~ tr{\\}{/}s;

    It's also possible to do everything in one step, but we're entering a golf course here:

    $script_dir =~ s{\\+(?=(.)?)}{"/"x defined $1}ge;
    Update: Talking about golf, this is shorter:
    $_ = s/\\+$//r =~ s{\\+}{/}gr for $script_dir;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Search & Replace repeating characters
by stevieb (Canon) on Apr 22, 2020 at 22:37 UTC

    This has the smell of an X-Y Problem.

    Can you explain the reasons for modifying the separators?

      I agree with that. I mean C:\\temp is an invalid path under Windows. It would be better to fix the thing that generates this invalid path rather than trying to hack that path into a valid path. The crux of an X-Y problem is that the OP is asking the wrong question or that the question is not well specified.
        "I mean C:\\temp is an invalid path under Windows."

        While I'm not disagreeing with that absolute statement, C:\\temp may be required under a Windows environment. I came across an example of this fairly recently.

        Consider a pp command on cmd.exe something like this (using Strawberry Perl):

        C:\some\dir>pp @long_list_of_options.txt -o filename.exe filename.pl

        Options (in long_list_of_options.txt) which include paths cannot be written like this for example:

        --link=C:\path\to\some.dll

        The parts like \X will be interpreted as backslashed escapes: resulting in just X, or special characters (e.g. newline, tab, and so on). The example option I showed would end up like:

        --link=C:path osome.dll

        In order to get it to resolve to the example shown, you'd need to write:

        --link=C:\\path\\to\\some.dll

        That doesn't mean that an XY Problem doesn't exist; it just shows that it might not exist. Having said that, the terminal \\\\ certainly looks highly dodgy.

        — Ken

      not an X-Y Problem. So that I can properly give an example of what I was trying to accomplish, I just assigned c:\\temp\\\\ to the variable $ScriptDir. in actuality, $ScriptDir gets its value from the terminal input from the end user $ScriptDir=<STDIN>; So I am trying to plan for the end user entering slashes and correct it

        I think you need to make your solution either smarter or not as helpfull, because Windows file paths are allowed to start with \\ in UNC notation. For example, this is a valid UNC filepath:

        \\servername\c$\foo.txt
        Ok. Now I understand this better.
        Use the command prompting loop to reject invalid syntax of the input.
        Below I reject input lines that have a double // or \\.
        use strict; use warnings; my $dir; while ( (print "enter directory; "), $dir=<STDIN> and $dir =~ /\\\\|\/ +\//g) { print "invalid directory syntax... double ", '// or \\\\', " not al +lowed!\n"; } $dir =~ s/^\s*|\s*$//g; #remove leading and trailing spaces print "INPUT LOOP says $dir\n"; __END__ C:\Monks>perl CommandLoopNoDoubleSlash.pl enter directory; C:\\x invalid directory syntax... double // or \\ not allowed! enter directory; D:\x\temp// invalid directory syntax... double // or \\ not allowed! enter directory; C://x invalid directory syntax... double // or \\ not allowed! enter directory; C:/X INPUT LOOP says C:/X
        Now it is also possible perhaps have a sub that prompts for a valid directory and that sub continues to loop until a valid directory is entered. I would return a file handle from that sub. In that sort of case, the sub tries to open the dir name that the user entered and it works or it doesn't. Loop until the openddir() works. Remember to allow for leading and trailing whitespace for all command line entries.
Re: Search & Replace repeating characters
by haukex (Archbishop) on Apr 23, 2020 at 19:54 UTC
    For example, my directory is "c:\\temp\\\\" (ending with 4 back slashes). ... $ScriptDir="C:\\temp\\\\";

    Note that this string doesn't end in four backslashes, it ends in two - "\\" represents a single backslash. Anyway, File::Spec's canonpath is your friend:

    use File::Spec::Win32; my $ScriptDir="C:\\temp\\\\"; print $ScriptDir,"\n"; # => C:\temp\\ $ScriptDir = File::Spec::Win32->canonpath($ScriptDir); print $ScriptDir,"\n"; # => C:\temp

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-19 19:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found