# paste_to_cbddd.pl paste to clipboard 24may12waw # DEVELOPMENTAL BRANCH ### STARTING DEVELOPMENTAL VERSION FOR BETTER HANDLING ### OF FANCY qq{} qx{} `` QUOTES, qr{} qr// REGEXEN, ETC. # replace '---' with 'ddd' everywhere for the developmental version. # to be invoked by ---.bat as: # perl C:\@Work\Perl\clipboard\paste_to_cb%0.pl %0 %* # where: # %0 is the base file name of the .bat file, # e.g., '---' for '---.bat'; # %* are any c.l. parameters supplied to the .bat file # upon invocation. # simplest invocation of .bat file: # --- # produces # perl -wMstrict -le # "multi-line # contents of windows clipboard # " =comment all switches and parameters immediately after the --- invocation (or ddd in the developmental version) control switches and parameters to be fed to the perl interpreter. if a -- switch is present, all parameters after the -- switch are fed directly to the script code being executed by -e or -E: --- -MData::Dump -- "<" ..\..\some\path\to\a\file.name produces perl -wMstrict -MData::Dump -le "multi-line contents of windows clipboard dd \%some_hash; more clipboard stuff " < ..\..\some\path\to\a\file.name note that the < input redirection operator must be "<" quoted initially to prevent its interpretation by the c.l. interpreter when the --- statement (batch file) is executed. when this operator appears among the script arguments, it is no longer quoted. it may be necessary to pass a literal character (e.g., something that may look like a re-direction operator) to the perl script. in this case, DOUBLE quote a SINGLE-quoted string. e.g., --- -E -- foo "'|'" "<" ..\..\some\path\to\a\file.name produces perl -wMstrict -lE "multi-line contents of windows clipboard " foo "|" < ..\..\some\path\to\a\file.name i.e., the "'|'" is passed to this script as '|' and is processed by this script to the "|" form in which it ultimately appears on the command line of the clipboard script invocation. --- command line switch processing: !abc 'a', 'b', 'c' switches are deleted from default switch set passed to the perl interpreter. switches may appear in any order. (untested: switches may be repeated.) mnemonic: switches are 'banged' (deleted). currently, default switches that can be deleted are: w -w warnings switch; s -Mstrict the strictures pragma; l -l 'auto-chomp' switch; e -e 'eval' switch (replaced by -E switch). -E -e will be replaced by -E (note: either -e or -E must always be present: it's a one-liner!) all other switches passed to --- (e.g., -n -p -MData::Dumper) are passed through to the perl invocation line. examples: --- perl -wMstrict -le (all defaults present) --- !w perl -Mstrict -le (suppress -w default) --- !ws perl -le (suppress both -w and -Mstrict defaults) --- !el perl -wMstrict -E (suppress -l and -e defaults, -e replaced by -E) --- -n !el perl -n -wMstrict -E (suppress -l and -e defaults, -e replaced by -E, use -n wrapper) --- -E perl -wMstrict -lE (suppress -e default (-l default remains), -e replaced by -E) switches can be passed to --- in any order. =cut # tested against AS 5.8.9, Strawberries 5.10.1, 5.12.3, 5.14.2 a/o # 00:20 20may12waw handle perl switches, script arguments. # general testing. # 21:30 13may12waw (FATAL => 'all') all expected changes. # general, not thorough, testing. # 16:00 10may12waw (FATAL => 'all') minor changes. # pragmata ######################################################### use warnings FATAL => 'all' ; use strict; # use diagnostics; # modules ########################################################## use Win32::Clipboard (); use Win32::Console 'STD_OUTPUT_HANDLE'; use Win32::GUI (); use Win32::GuiTest (); use List::MoreUtils qw(first_index); # prototypes ####################################################### # # none # globals, constants, declarations, etc. ########################### # debug, development and testing control constants. use constant { DEVEL => 1, DEBUG => 0, TEST_STRING => 0, }; use constant { # various debug print points PDB_1 => DEBUG && 0, PDB_2 => DEBUG && 0, PDB_3 => DEBUG && 0, }; # perl executable invocation switch defaults. use constant DEFAULTS => ( w => 'w', # -w warnings switch s => 'Mstrict', # strictures pragma l => 'l', # -l 'auto-chomp/newline print' switch e => 'e', # -e 'eval' switch (-E for latest features) ); # all switches after this switch passed directly to script. use constant END_OF_SWITCHES => '--'; =comment some test scripts my %dict = qw(foo BAR baz W00T zonk ZOTS); ;; my $close_tag = qr{ }xms; ;; my $s = 'foo baz zonk'; ;; my $close_tag = qr{ }xms; $s =~ s{ (\w+) ($close_tag) (\w+) } { replace($1, $2, $3, \%dict) }xmsge; print qq{'$s'}; ;; sub replace { my ($one, $two, $three, $hr) = @_; ;; my $s = qq{$one$three}; return qq{$one$two$three} unless $hr->{ $s }; ;; my $r = $hr->{ $s }; my $one_r = substr $r, 0, length($one); my $three_r = substr $r, length($one); return qq{$one_r$two$three_r}; } my @output = qx{ ls }; # some test code printf qq{+@ARGV+ $_} for @output; ## following to be invoked with -- args: ## -- "<" ..\..\..\moby\mwords\354984si.ngl ## (or equivalent dictionary file). while () { # words in which all vowels present once each chomp; my $s = $_; tr{aeiou}{}cd; next if $_ ne 'aeiou'; # aeiou in that specific order # next if 5 != length $_; # aeiou in any order # next if eval qq{ sub { (\$_ = 'aeiou') =~ tr{$_}{}d != 5 }->() }; # # also eval qq{ sub { \$_ = 'aeiou'; tr{$_}{}d != 5; }->() }; # next if 5 != length $_ # aeiou in any order # or eval qq{ sub { (\$_ = 'aeiou') =~ tr{$_}{}d != 5 }->() }; # also or eval qq{ sub { \$_ = 'aeiou'; tr{$_}{}d != 5; }->() }; # also or (my $t = 'aeiou') =~ s{ [$_] }{}xmsg != 5; print qq{'$s'}; } ## following invoked with -n and -- args (no < input redirection): ## -n -- ..\..\..\moby\mwords\354984si.ngl ## (or equivalent dictionary file) (ASSUMES -l switch asserted). # words in which all vowels present once each my $s = $_; tr{aeiou}{}cd; next if $_ ne 'aeiou'; # aeiou in that specific order # next if 5 != length $_; # aeiou in any order # next if eval qq{ sub { (\$_ = 'aeiou') =~ tr{$_}{}d != 5 }->() }; # # also eval qq{ sub { \$_ = 'aeiou'; tr{$_}{}d != 5; }->() }; # next if 5 != length $_ # aeiou in any order # or eval qq{ sub { (\$_ = 'aeiou') =~ tr{$_}{}d != 5 }->() }; # or eval qq{ sub { \$_ = 'aeiou'; tr{$_}{}d != 5; }->() }; # or (my $t = 'aeiou') =~ s{ [$_] }{}xmsg != 5; print qq{'$s'}; use Modern::Perl; say map {(split)[1]} @ARGV; arguments: "foo [ABC/1/2/3] [2nd] bar" "fee [DEF/4/5/6] [fie] [foe] fum" =cut # main program ##################################################### SETUP: { # capture, process options, constants (some critical) # many private variables exposed through constant subs. # script invocation parameters. my $cmd_file_name = shift; # .bat or .cmd file name defined $cmd_file_name or die "no .cmd file name passed"; sub CMD_FILE_NAME () { $cmd_file_name } # find index of end-of-switches marker, if any, in arguments. my $eosi = first_index { $_ eq END_OF_SWITCHES } @ARGV; # find end indices of switch and argument array slices. $eosi = @ARGV if $eosi < 0; # marker not found my ($si, $ai) = ($eosi-1, $eosi+1); # extract switch and argument array slices, discard delimiter. my @switches = @ARGV[ 0 .. $si ]; # to perl executable my @arguments = @ARGV[ $ai .. $#ARGV ]; # to executed script # find, flag and remove -E switch in perl switch args, if any. my $Ei = first_index { $_ eq '-E' } @switches; # -1 if absent sub BIG_E () { ($Ei > -1) } splice(@switches, $Ei, 1) if BIG_E; # remove switch if present # double-quote script args (strings) that have embedded space(s). # e.g., # --- -- "foo bar" baz ">" filename # becomes # "foo bar" baz > filename # in the perl script invocation. m{\s} and $_ = qq{"$_"} for @arguments; # convert single-quoted arguments to double-quoted args. s{ \A ' | ' \z}{"}xmsg for @arguments; # expose r/o switches for perl executable and script. sub PERL_SWITCHES () { @switches } # caution: SHALLOW copy # expose r/o supplementary arguments for executed perl code. sub SCRIPT_ARGS () { @arguments } # caution: SHALLOW copy # current windows console info. # my $con_out = new Win32::Console(STD_OUTPUT_HANDLE); my $con_out = Win32::Console->new(STD_OUTPUT_HANDLE); $con_out or die "new Win32::Console failed"; sub CON () { $con_out } # for Console experiments: maybe delete? my ($con_cols) = $con_out->MaxWindow; defined $con_cols or die "console MaxWindow failed"; sub CONSOLE_WIDTH () { $con_cols } my ($col, $row) = $con_out->Cursor; defined $row or die "console Cursor failed"; my $prev_line = $con_out->ReadChar(CONSOLE_WIDTH, $col, $row-1); defined $prev_line or die "console ReadChar failed"; sub SHELL_INVOCATION { $prev_line } # DO NOT Close if CON defined. # $con_out->Close; # ??? Close not implemented in 0.031 # ASSUME windows c.l. shell prompt string is immediately before # command/batch file name on c.l., with possible intervening # whitespace. OFFSET of 1st char of cmd file name (or of # preceding whitespace, if any) is LENGTH of shell prompt # string, or default to 0 if cmd file name cannot be # recognized. my $prompt_width = $prev_line =~ m{ (\s* \Q$cmd_file_name\E) }xms ? $-[1] : 0; sub PROMPT_WIDTH () { $prompt_width } # current clipboard text for ultimate restoration. my $clipboard_text = Win32::Clipboard::GetText(); defined $clipboard_text or die "failed to get clipboard text"; sub CLIPBOARD_TEXT () { $clipboard_text } } # end SETUP block MAIN: { # begin main loop # warn "script arg(s): ``@{[ join q{'' ``}, SCRIPT_ARGS ]}''" if SCRIPT_ARGS; # warn "perl switches(es): ``@{[ join q{'' ``}, PERL_SWITCHES ]}''" if PERL_SWITCHES; print "RUNNING: $0 -------------\n" if DEBUG; # get standard perl code for conversion for windows c.l. pasting. my $pc = (DEBUG or TEST_STRING) ? <<'PC' : CLIPBOARD_TEXT; print "\noutput: \n"; print "now is \"the\" time # fake \"comment\" in \"-string # another fake \"comment\" in \"-string for all good men \n"; print 'four "score" and # fake "comment" in \'-string # another fake "comment" in \'-string seven \'years\' ago # also fake "comment"'; # real comment # another real comment print qq(\n\n); $" = "\"-string with \" and ' chars"; print qq{$" \nagain: ${"} \n}; $" = '\'-string with " and \' chars'; print ${"}, "\n"; print "\n\n"; print "1-bsl-qq: \\\" \n"; print "2-bsl-qq: \\\\\" \n"; print "3-bsl-qq: \\\\\\\" \n"; print "\n\n"; my @ra; $" = ${"} = "."; @ra = ("foo", 'bar', "\"", '\"'); print "@ra \n"; # ###### # how are specials treated? $" = ' '; $" = ' '; print "2-bsl-qq: \\\\\" \n"; $" = ' '; print 'a', 5 > 3, 3 < 5, 1 | 1, 1 ^ 0, 8 >> 3, 1 << 3, '^^', "\" \n"; print 'b', 5 > 3, 3 < 5, 1 | 1, 1 ^ 0, 8 >> 3, 1 << 3, '^^', "\" \n"; $" = ' '; my $x = "\""; $x = "\""; print 'c', 5 > 3, 3 < 5, 1 | 1, 1 ^ 0, 8 >> 3, 1 << 3, '^^', "\" \n"; print 'd', 5 > 3, 3 < 5, 1 | 1, 1 ^ 0, 8 >> 3, 1 << 3, '^^', "\" \n"; # ##### after specials PC defined $pc or die "clipboard Get undefined"; # for DEVELopment. $pc .= "\nEND { print qq{developmental: $]/compiled; \$]/run \\n} }" if DEVEL; print "RAW: -------------\n$pc" if DEBUG; $pc = fix_quoted_matter($pc); print "AFTER QUOTED MATTER FIXUP: ---------\n$pc\n---\n" if DEBUG; # escape remaining " characters to avoid interpretation by # windows c.l. interpreter. $pc = escape_dquotes($pc); # at this point, every " should be prefixed with at least 1 '\' char. print "AFTER QQ FIXUP: -------------\n$pc\n---\n" if DEBUG; # handle special < | > ^ windows shell metacharacters: redirection # commands and escape for the windows command line interpreter. $pc = escape_shell_specials($pc); print "AFTER SHELL SPECIALS FIXUP: -----------\n$pc\n---\n" if DEBUG; # remove remaining newlines in input code, pad lines to console width. # this should be done after everything else has been fixed up, # escaped, etc., so that the lines of input code are at their # final length and can be padded properly. $pc = fix_linebreaks($pc); print "AFTER LINEBREAKS FIXUP: -------------\n$pc\n---\n" if DEBUG; # assemble entire command line for clipboard my $cl = pad_con_cols(cl_invocation(), PROMPT_WIDTH) . qq{"$pc} ; # because of way pad_con_cols() pads, last character of perl # code string should always be a space, but replace last char # conditionally just in case when adding closing command line quote. $cl =~ m{ [ ] \z }xms or warn "perl code string ends in non-space"; $cl =~ s{ [ ]? \z }{"}xms; # add supplementary arguments to script, if any. $cl .= " @{[ join ' ', SCRIPT_ARGS ]}" if SCRIPT_ARGS; my $paste_err = paste_via_keys($cl) # paste_via_mouse($cl, CLIPBOARD_TEXT) # sometimes extra 'P' with 5.10.1 ?? ; die "SendKeys failed: $paste_err" if $paste_err; } # end MAIN loop # subroutines ###################################################### # send keys only to command line of console window from which # the bat file was executed that invoked, in turn, this script. # this console window is always foreground window because that's # where user just typed bat file name, so no need to worry about # positioning/re-positioning cursor for clipboard paste via # mouse right-click. # however, keys are output noticeably slowly even with # a SendKeys() delay parameter of 0. sub paste_via_keys { my ($command_line, # paste to script's window $key_delay, # optional: milliseconds to delay per key ) = @_; $key_delay ||= 0; # default key delay $command_line = fix_for_sendkeys($command_line); # more escapes return Win32::GuiTest::SendKeys($command_line, $key_delay); } # set clipboard with perl command line using mouse and # console window paste. # even with 5 retries, this version of pasting fails occasionally! sub paste_via_mouse { # return 0/0; # if new pad_con_cols() unaccomodated my ($command_line, # paste to script's window $old_clipboard, # old clipboard contents to restore ) = @_; my $tries = 5; # clipboard set attempts; still fails w/5 # load c.l. into clipboard. SET_TRY: { Win32::Clipboard::Set($command_line) and last SET_TRY for 1 .. $tries; return "clipboard Set (for paste) failed: $tries tries"; } # re-position cursor into console window running this script. # save previous cursor position for later restoration. my ($old_cursor_x, $old_cursor_y) = put_cursor_in_console(); # paste clipboard contents into current active console window # command line. # ASSUMPTION: Win32::GuiTest::SendMouse and SendKeys return # some kind of error description string or non-zero error code # on failure; documentation doesn't say this, implies void return. my $guitest_err; $guitest_err = Win32::GuiTest::SendMouse("{RIGHTCLICK}"); return "SendMouse failed: $guitest_err" if $guitest_err; $guitest_err = Win32::GuiTest::SendKeys('P'); # Paste clipboard return "SendKeys failed: $guitest_err" if $guitest_err; # resets cursor position. Win32::GUI::SetCursorPos($old_cursor_x, $old_cursor_y); # restore original contents of clipboard. RESTORE_TRY: { Win32::Clipboard::Set($old_clipboard) and last RESTORE_TRY for 1 .. $tries; return "clipboard Set (for restore) failed: $tries tries"; } return ''; # all ok: no error message } # end sub paste_via_mouse() # re-position cursor into console window running this script. # return previous cursor position for later restoration. sub put_cursor_in_console { my ($cursor_x, $cursor_y) = Win32::GUI::GetCursorPos(); my $fgw = Win32::GUI::GetForegroundWindow(); my ($left, $top, $right, $bottom) = Win32::GUI::GetAbsClientRect($fgw); # both methods for figuring, setting mouse cursor in console # window work. first is simpler, second puts cursor # smack dab in middle of console window, fwiw. Win32::GUI::SetCursorPos( $left, $top # top-left corner # ($left+$right)/2, ($top+$bottom)/2 # smack dab in middle ); # return mouse cursor pos'n before it was put in console. return ($cursor_x, $cursor_y); } # parse out "- and '-quoted strings for processing. # make embedded newlines INSIDE quoted strings into sequences # appropriate for a double- or single-quoted string. # also, make newlines OUTSIDE of quoted strings (along with # any whitespace and possible # comments-to-end-of-line) # into a marker for later fix-up. # # newlines can be embedded in single- and double-quoted strings. # (also in here-docs, of course, but this script does NOT handle # here-docs.) # in double-quoted strings, find embedded newlines and replace # with explicit '\n' escape sequences so the processed c.l. # string will display the same as the original source. # in single-quoted strings, replace embedded newlines with a # visible text tag indicating the presence of the embedded # newline at that position in the original source string. # NOTE: these transformations are also carried out on other # things that look like "- and '-quoted strings but that may # actually be contained in something like a qq{} string, # m{ ... } regex, etc! # this is possibly even more confusing because while embedded # newlines are handled in "- and '-quoted strings, they are NOT # handled in qq{} and q{} (and other, similar constructs) -- UNLESS # they should happen to be within "- or '-pairs that appear in those # constructs and so resemble "- or '-quoted strings! # a solution would be to properly handle ALL quote-like constructs, # but that's hard. sub fix_quoted_matter { my ($perl_code, # perl source string ) = @_; # utility regexes -- CAUTION: no utility regex may capture. # all regexes compiled with //o switch. # tricky (to parse) scalars have highest 'precedence'. # have to parse $" and ${"} first because # " begins "-quoted string if not $" or ${"} scalar. # have to parse $# and ${#} first because # # begins comment-to-eol otherwise. # note: $\s*" $\s*{\s*"} both interpreted as $" by perl, # likewise with $#. # there shall be NO space between " or # and closing } . # note: " $" \n" and " ${"} \n" are not parsed by perl. # qq{ $" \n} and qq{ ${"} \n} are parsed. # " $\" \n" and " ${\"} \n" are parsed. # $# and ${#} do not seem to be interpolated. my $sc = qr{ ["\043] }oxms; # \043 vice '#': syntax hltg. my $tricky_scalars = qr{ \$ \s* (?: { \s* $sc} | $sc ) }oxms; # single- and double-quoted strings have next and equal # precedence: "s may appear in '-quoted strings and vice-versa. # precedence is higher than newlines because strings may have # embedded newlines. my $d_quoted = qr{ [^"\\]* (?: \\. [^"\\]* )* }oxms; my $s_quoted = qr{ [^'\\]* (?: \\. [^'\\]* )* }oxms; # newlines (and possible comments-to-end-of-line) have # lowest precedence. exclude recognition of $# as comment. # (representing '#' as "\043" keeps syntax highlighter happy.) my $ceol = qr{ (?. # regex compiled with //o switch. $body =~ s{ \r? \n } ''xmsog; # can't convert '-quoted strings to q{} just to # match " conversion because that screws up \' single- # quote escaping in original '-quoted string. return "'$body'"; } sub fix_linend { my ($block, # one or more line ends, empty lines (w/comments) ) = @_; # replace line end(s) with a unique string to mark # an original line break or breaks for later fixup. return "\n"; # a single newline is unique enough for now } # escape remaining " characters to avoid interpretation by # windows c.l. interpreter. # these " chars may already be escaped with one or more '\' chars. # the 'rule' seems to be that the number of existing '\' chars # be doubled, and that an additional '\' is added before the '"'. sub escape_dquotes { my ($perl_code, # perl code string ) = @_; # regex compiled with //o switch. $perl_code =~ s{ (\\*) (") } { $1 x 2 . qq{\\$2} }xmsoge; return $perl_code; } # handle special < | > ^ & windows shell metacharacters, # redirection commands and escape for the windows command # line interpreter. # the 'rule' (?) seems to be that special characters are escaped # (with a '^' char) if they are preceded in the string by # an ODD number of '\"' char pairs! (note that these pairs # may be part of a sequence with any number of backslashes # preceding; no matter: just the number of '\"' count.) sub escape_shell_specials { my ($perl_code, # perl code string ) = @_; # all regexes compiled with //o switch. my $special = qr{ [<|>^&] }xmso; # added & 13jun12waw my $bsl_qq = qr{ \\" }xmso; my $not_bsl_qq = qr{ (?! $bsl_qq) . }xmso; my $bsl_qq_or_eos = qr{ $bsl_qq | \z }xmso; $perl_code =~ s{ ($bsl_qq $not_bsl_qq* $bsl_qq_or_eos) } { local $_ = $1; s{ ($special) }{^$1}xmsog; $_ }xmsoge; return $perl_code; } # remove remaining newlines in input code, pad lines to console width. sub fix_linebreaks { my ($perl_code, # perl code string ) = @_; # all regexes compiled with //o switch. # linebreak/not_linebreak regexes could be expressed as char # set and its complement, but this allows easy expansion to # multi-char string for line-break marker if needed. my $linebreak = qr{ \n }xmso; my $not_linebreak = qr{ (?! $linebreak) . }xmso; # $linebreak + quantifier below probably redundant, seems benign. $perl_code =~ s{ \G ($not_linebreak*) $linebreak+ } { pad_con_cols($1) }xmsoge; return $perl_code; } # more fix-ups for more special characters significant to the # Win32::GuiTest::SendKeys() function. sub fix_for_sendkeys { my ($command_line, # escape special characters ) = @_; $command_line =~ s< ([~+^%(){]) > {{$1}}oxmsg; # compiled with //o switch return $command_line; } # suppress perl default switches specified in default c.l. switches. sub suppressed { my (%switches) = @_; # process all !abc switches. my @kill_switches = map m{ (?: \G (?perl -wMstrict -e "print \" \\\" \"" " C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\" \"" \" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\" \"" \\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\\\" \"" \\\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\\\\\\\" \"" \\\\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\\\\\\\\\\\" \"" \\\\\" backslashed " in "" string: input output string string 3 0 7 1 11 2 15 3 19 4 23 5 ------------------------------------------------------- backslashed " in q{} string input output string string 1 0 3 1 5 1 7 2 9 2 11 3 13 3 15 4 17 4 C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \" }" " C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\" }" \" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\" }" \" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\\\" }" \\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\\\\\" }" \\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\\\\\\\" }" \\\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\\\\\\\\\" }" \\\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print q{ \\\\\\\\\\\\\\\" }" \\\\" backslash interpolation experiments: C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\" \"" " C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\" \"" String found where operator expected at -e line 1, at end of line (Missing semicolon on previous line?) Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\" \"" \" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\" \"" String found where operator expected at -e line 1, at end of line (Missing semicolon on previous line?) Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\" \"" \\" C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\" \"" String found where operator expected at -e line 1, at end of line (Missing semicolon on previous line?) Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\\" \"" Can't find string terminator '"' anywhere before EOF at -e line 1. C:\@Work\Perl\clipboard>perl -wMstrict -e "print \" \\\\\\\\\\\\\\\" \"" \\\"