KSH - echo Windows path and special characters - special-characters

so I'm receiving a Windows path as argument but since in the path there are special chars I'm having some trouble.
For example if the argument path ($1) is \test\bla the outout of the script it's "\SLE esla" (because of the \t and \b)
How can I print the correct path??
Thanks.
p.s.
maybe it's a stupid question but I'm new to ksh

as I said I'm new to ksh but here is the solution:
print -R $arg
Using print instead of echo make it possible to avoid the expansion of "\" with the "-R" option

Related

why does changing from ' to " affect the behavior of this one-liner?

Why is it that simply changing from enclosing my one-liner with ' instead of " affects the behavior of the code? The first line of code produces what is expected and the second line of code gives (to me!) an unexpected result, printing out an unexpected array reference.
$ echo "puke|1|2|3|puke2" | perl -lne 'chomp;#a=split(/\|/,$_);print $a[4];'
puke2
$ echo "puke|1|2|3|puke2" | perl -lne "chomp;#a=split(/\|/,$_);print $a[4];"
This is the Perl version:
$ perl -v
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi
ARRAY(0x1f79b98)
With double quotes you are letting the shell interpolate variables first.
As you can check, $_ and $a are unset in the subshell forked for pipe by the parent shell. See a comment on $_ below.
So the double-quoted version is effectively
echo "puke|1|2|3|puke2" | perl -lne 'chomp;#a=split(/\|/);print [4];'
what prints the arrayref [4].
A comment on the effects of having $_ exposed to Bash. Thanks to Borodin for bringing this up.
The $_ is one of a handful of special shell parameters in Bash. It contains the last argument of the previous command, or the pathname of what invoked the shell or commands (via _ environment variable). See the link for a full description.
However, here it is being interpreted in a subshell forked to run the perl command, its first. Apparently it is not even set, as seen with
echo hi; echo hi | echo $_
which prints an empty line (after first hi). The reason may be that the _ environment variable just isn't set for a subshell for a pipe, but I don't see why this would be the case. For example,
echo hi; (echo $_)
prints two lines with hi even though ( ) starts a subshell.
In any case, $_ in the given pipeline isn't set.
The split part is then split(/\|/), so via default split(/\|/, $_) -- with nothing to split. With -w added this indeed prints a warning for use of uninitialized $_.
Note that this behavior depends on the shell. The tcsh won't run this with double quotes at all. In ksh and zsh the last part of pipeline runs in the main shell, not a subshell, so $_ is there.
This is actual a shell topic, not a perl topic.
In shell:
Single quotes preserve the literal value of all of the characters they contain, including the $ and backslash. However, with double quotes, the $, backtick, and backslash characters have special meaning.
For example:
'\"' evaluates to \"
whereas
"\'" evaluates to just '
because with double quotes, the backslash gets a special meaning as the escape character.

sed system command in perl script

I am trying to put the system command like below to the perl script, but
sed expression contains both quotes and backticks and I am not sure how to escape all of them, so it will execute my system command exactly as I need.
Here is the example of the command:
mysql -u root -D porta-billing -e "..." | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g"
The answer to the question you're asking is to use the qx(...) operator. qx(...) is the "choose your own delimiter" version of backticks.
my $output = qx[ ... ];
Or
my $output = qx( ... );
Or
my $output = qx! ... !;
It's easy to find a delimiter that won't clash with the characters in your command string.
But the answer to the question that you should be asking has two parts:
Don't call mysql from your Perl program - use DBI instead.
Don't call sed from your Perl program - use Perl code to manipulate your text.
I feel slightly nervous about the first part of my answer as I'm worried you will just take my hacky workaround and end up with an unmaintainable mess. Please take note of the advice in the second half - even if you ignore it in this case.

How to process a file in Perl - handling variables from Bash: disappearing "." character

I need to find the age of a file in seconds but when I give my Perl line:
perl -e ' my #st=stat("$name"); print time - $st[9];'
a variable from Bash with "." in the filename, it won't find the file and prints the systime instead. Otherwise, if I create a file with a name such "something", it works perfectly well.
I tried escaping the character with \ but that does not work. I really do not know Perl and I don't know how to figure this out.
Thanks for the help!
(Please, do not suggest any BASH only workarounds, lot of stuff here is old, truncated...)
EDIT: I found a workaround but I can't post an answer to my own question since I am a newbie, so here it is:
So I finally found a workaround.
You export the variable in Bash:
export name=".file.txt"
and then call it from the Perl like this: $ENV{name}
and it works just fine.
EDIT 2:
The export idea was just a temporary solution. Better one is using single quotes as perreal suggested.
You need to put the shell variable out of the single quotes:
perl -e ' my #st=stat("'"$name"'"); print time - $st[9];'
or pass it through arguments:
perl -se 'my #st=stat("$name"); print time - $st[9];' -- -name="$name"

Use of pipe within backtick command

I'm having an issue with some code and I'm wondering if anyone can assist.
Basically I'm trying to execute an isql query against a database and assign it to a scalar variable. The isql command makes use of the column seperator which is defined as the pipe symbol.
So I have it set-up as such:
my $command = "isql -S -U -s| -i";
my $isql_output = `$command`;
The isql command works in isolation but when issued as a backtick it stops at the pipe. I've tried concatenating the $command string using sub-strings, using single quotes and backslash escaping items such as -s\"\|\" to no avail. I've also tried using qx instead of backticks.
Unfortunately I'm currently using an older version of perl (v5.6.1) with limited scope for upgrade so I'm not sure if I can resolve this.
You have to quote the | in a way that the shell does not recognize it as a special character. Two ways:
Put the -s| into single quotes: '-s|'. Perl will leave single quotes inside double quoted strings alone and pass them to the shell unmodified.
Escape the | with two backslashes: -s\\|. Why two? The first one is seen by Perl telling it to pass the next character through unmodified. Therefore the shell sees -s\| and does something very similar: it sees the single \ and knows not to treat the next char, |, special.
The problem is that the command is being executed through a shell.
You can avoid this by passing the command and arguments in a list rather than a single string.
The backtick construct does not support that, so you would need to use the open() function instead.
I haven't tested the following code but it gives the idea:
my #command = (qw(isql -Sserver -Uuser -Ppassword -s| -w4096), '–i' . $file);
print join(' ', #command), "\n";
open(my $fh, '-|', #command)
or die "failed to run isql command: $#\n";
my #isql_output = <$fh>;
close($fh);
my $isql_output = $isql_output[0]; chomp($isql_output);
If you're working with a 15 year old version of Perl (which Oracle users tend to do) I'm not sure this will all be supported. For instance, you may need to write chop instead of chomp.
UPDATE: the problem is not the Perl version, but this construct not being supported on Windows, according to the documentation. This must be qualified: I use Perl on Cygwin and it works fine there, but I don't know whether you can use Cygwin.
Single quotes should work. Try to run test perl script:
my $cmd = "./test.sh -S -U -s '|' -i";
print `$cmd`;
With test.sh:
#!/bin/sh
echo $#
Output should be -S -U -s | -i

How to properly use filepath with arguments spaces in them, in Perl?

Looking to open a file at '"E:\\Program Files (x86)\\Vim\\vim73\\gvim.exe -f " %s" "' and I'm getting Cannot find e:\Program.
What do I need to do to get it to work?
edit: Here's the script I am trying to get working (it's the full script as I'm not yet familar with perl at all, sorry). It's supposed to launch gvim when I make a POST request to the server via chrome's TextAid. Check out line 38
It's either single\double-quoting the path or escaping the spaces with backslashes.
system
sprintf
'"E:\\Program Files (x86)\\Vim\\vim73\\gvim.exe" -f "%s"',
$file;
I find it safer/easier to use forward slashes.
my $file = 'C:/Program Files (x86)/Adobe/Reader 10.0/Reader/AcroRd32.exe' ;
system $file ;
If you need parameters to the cmmmond
my $file = '"C:/Program Files (x86)/Adobe/Reader 10.0/Reader/AcroRd32.exe"' ;
my $data = '"C:\working_dir/music/interim/a b.pdf"' ;
system "$file $data" ;
Using single quotes makes it easier to embed double quites without having to escape things.
One way to handle this is to mess about with quoting and escapes. You need to be sure to individually quote the command and each argument to the command as a separate string.
Also, on win32 you can use real slashes instead of backslashes for directory separators. So:
system( sprintf '"E:/Program Files (x86)/Vim/vim73/gvim.exe" -f "%s"', $file );
The other, easier option is to use a list of arguments with system().
Line 38:
my #EDITOR_COMMAND = ( 'E:/Program Files (x86)/Vim/vim73/gvim.exe', '-f' );
Line 185/186:
system( #EDITOR_COMMAND, $file );
Then all the pesky quoting is taken care of for you.
our $EDITOR_CMD = "'E:\\Program Files (x86)\\Vim\\vim73\\gvim.exe' -f %s";