I have a problem trying to put single quotes around a text - perl

I have a password that has special character with an exclamation point.
ABcD!987zyz12388
I'd like to put single quotes around it. This password is fetched and saved to a variable.
$mypass=`fetchpwd $sourceserver $loginacct`;
$mypass="'$mypass'";
print "My password is: $mypass\n";
The return looks like this
My Password is 'ABcD!987zyz12388
'
The end single quote went on the next line. How can I have the last single quote right after the last 8 to something like this 'ABcD!987zyz12388'

Use chomp to remove the newline character which is added by your fetchpwd command. Do this before you add single quotes.
$mypass=`fetchpwd $sourceserver $loginacct`;
chomp $mypass;
$mypass="'$mypass'";
print "My password is: $mypass\n";

You have a good answer already, but I wanted to share a little programmer trick that might have helped you work out what the problem was by yourself.
You thought that it was adding the quote to your string that was causing the problem. And your program demonstrates that:
$mypass=`fetchpwd $sourceserver $loginacct`;
$mypass="'$mypass'";
print "My password is: $mypass\n";
When you're investigating data being "corrupted" like this, one good first step is to identify exactly when the corruption occurs. And you can do that by printing your data whenever there's a chance that it changes. In this case, it's a good idea to print $mypass as soon as it is first set and before you do anything with it:
$mypass=`fetchpwd $sourceserver $loginacct`;
print "My password is: $mypass\n";
$mypass="'$mypass'";
print "My password is: $mypass\n";
Now, that would have given you two newline characters (the one you explicitly print, but also the extra one that you get from fetchpwd - the one that is causing your problems. And sometimes, two consecutive newlines are hard to spot. So it's a good idea to put characters around values that you're trying to print. I like to use <...>:
$mypass=`fetchpwd $sourceserver $loginacct`;
print "My password is: <$mypass>\n";
$mypass="'$mypass'";
print "My password is: <$mypass>\n";
That would have shown you that the extra newline was present right from the start and, therefore, you adding quotes around it wasn't what was corrupting it. And, hopefully, it would have led to you investigating exactly what was returned by fetchpwd.

Related

Getting Error of Modification of a read-only value attempted

I am trying to select the below value from database:
Reporting that one of #its many problems had been the recent# extended
sales slump in women's apparel, the seven-store retailer said it would
start a three-month liquidation sale in all of its stores.~(A) its
many problems had been the recent~(B) its many problems has been the
recently~(C) its many problems is the recently~(D) their many problems
is the recent~(E) their many problems had been the recent~
i am selecting this value in variable $ques and then selecting a text as below:
$ques=~s/^(.*?)\#(.*?)\#(.*?)$/$2/;
Now, while replacing the ~ character in the string by
$3=~s/~/\n/g; ---->line 171
and running the script, I am getting one error as:
Modification of a read-only value attempted at main.pl line 171
I want to replace all the ~ character with '\n' and print the final value. Please suggest how to do it.
*I have researched this on net, but got confused that how to handle these read only variables.
You've already got a good explanation of the problem from José Castro. But there's another solution if you're using a recent-ish version of Perl (Update: having checked more carefully, I find that means 5.14+). The /r argument to the substitution operator will copy your string, make the substitution on the copy and then return that altered value.
So you could write:
my $new_value = $3 =~ s/~/\n/rg;
It sounds like what you really want in this case is split rather than regular expression capture groups:
my #parts = split(/#/, $ques);
$parts[2] =~ s/~/\n/g;
It makes the intent of your code clearer since you are, in fact, splitting on # symbols.
Just like you say, the special variables $1, $2, etc., are read-only, and that means that you can't perform that substitution on them.
Performing the substitution on $ques will do what you need:
$ques =~ s/~/\n/g;
print $ques;
Do note that in the earlier substitution that you're performing on $ques you're getting rid of all the ~ characters.

Exception calling "Substring" with "2" argument(s):

I am trying to create a username based on first and last name. I want just the first initial of the username. When I try the code below I get this error
Import-Csv "C:\Users\Alex.piwowar.adm.j2global\desktop\ExcelMicroADAdd.csv" | ForEach-Object{
$First=$_."First"
$Last=$_."Last"
$Location=$_."Location"
$Title=$_."Title"
$Department=$_."Department"
$ManagerName=$_."Manager"
$Company=$_."Company"
$FirstIntitial = $First.Substring(0,1)
}
From my understanding what I entered will start at the beginning of $First and move over one which should be the first letter.
Am I thinking incorrectly?
You assertion of how your code is supposed to work is correct. My assumption here is that $first is a zero-length string. I can get this error from doing the following:
"".Substring(0,1)
The error is stating that the string is not long enough to return one characters. Zero-length would explain that.
Have a look at your source data possibly or debug $first/$_.First at the time of failure. Also you don't need to use quotes on single word properties. Just ones with special characters or spaces.
Once you get that issue figured out....If you only wanted the first character though you can treat string like a character array to just return the first character. I do so when making my new account scripts
$FirstIntitial = $First[0]

Retrieving String with single quotes from database and storing in Perl

I have a SQL query
select name from Employee
Output :
Sharma's
How can I store this output in perl string.
I tried below :
$sql =qq {select Name from Employee};
$Arr = &DataBaseQuery( $dbHandle, $sql );
$name = $Arr;
But when I print $name I get output as
Sharma::s
How can I store the single quote in the $name.
First of all, non of standard DBI/DBD exibits behavior you listed, in my experience.
Without knowing details of what DataBaseQuery() does it's impossible to answer conclusively, but a plausible theory can be formed:
Apostrophe is a valid package separator in Perl, equivalent to "::".
Reference: perldoc perlmod
The old package delimiter was a single quote, but double colon is now the preferred delimiter, in part because it's more readable to humans, and in part because it's more readable to emacs macros. It also makes C++ programmers feel like they know what's going on--as opposed to using the single quote as separator, which was there to make Ada programmers feel like they knew what was going on. Because the old-fashioned syntax is still supported for backwards compatibility, if you try to use a string like "This is $owner's house" , you'll be accessing $owner::s ; that is, the $s variable in package owner , which is probably not what you meant. Use braces to disambiguate, as in "This is ${owner}'s house" .
perl -e 'package A::B; $A::B=1; 1;
package main;
print "double-colon: $A::B\n";
print "apostrophe: $A'"'"'B\n";'
double-colon: 1
apostrophe: 1
I have a strong suspicion something within your own libraries inside DataBaseQuery() call was written to be "smart" and to convert apostrophes to double-colons because of this.
If you can't figure out root cause, you can always do one of the following:
Write your own DB wrapper
Assuming your text isn't likely to contain "::", run a regex to fix s#::#'#g; on all results from DataBaseQuery() (likely, in a function serving as a wrapper-replacement for DataBaseQuery())

PowerShell console host displays strings inconsistently

When I run this in PowerShell ISE, both strings are displayed identically.
When I run it in the console host, string $a is missing the empty line.
Why is that, and can I work around it?
I want to format blocks of text without using `n
$a = "there should be one emtpy line
between these two lines of text"
$b = "there should be one emtpy line`n`nbetween these two lines of text"
$a
$b
If you type that into the console host, you're correct; it won't work as expected. But if you save it in a file, then it does work as expected (the blank line is preserved).
I believe that this is because of the way the console host is using blank lines to interpret your input, since it needs to detect blank lines to tell when to stop input in some cases.
I don't know enough to know if it's a bug.
Something else that may not be clear is that when you write the way you're assigning it to $a, you're actually inserting CR and LF ("`r`n") when in the ISE host, whereas with $b you're just using LF. In the console host, a LF only is used.
To see that, I like to use [RegEx]::Escape:
[RegEx]::Escape($a)
[RegEx]::Escape($b)
Using this I was able to confirm that using the console host to enter the strings, the second LF is actually not present in the $a string; it's not simply a display issue.

Perl: pattern match a string and then print next line/lines

I am using Net::Whois::Raw to query a list of domains from a text file and then parse through this to output relevant information for each domain.
It was all going well until I hit Nominet results as the information I require is never on the same line as that which I am pattern matching.
For instance:
Name servers:
ns.mistral.co.uk 195.184.229.229
So what I need to do is pattern match for "Name servers:" and then display the next line or lines but I just can't manage it.
I have read through all of the answers on here but they either don't seem to work in my case or confuse me even further as I am a simple bear.
The code I am using is as follows:
while ($record = <DOMAINS>) {
$domaininfo = whois($record);
if ($domaininfo=~ m/Name servers:(.*?)\n/){
print "Nameserver: $1\n";
}
}
I have tried an example of Stackoverflow where
<DOMAINS>;
will take the next line but this didn't work for me and I assume it is because we have already read the contents of this into $domaininfo.
EDIT: Forgot to say thanks!
how rude.
So, the $domaininfo string contains your domain?
What you probably need is the m parameter at the end of your regular expression. This treats your string as a multilined string (which is what it is). Then, you can match on the \n character. This works for me:
my $domaininfo =<<DATA;
Name servers:
ns.mistral.co.uk 195.184.229.229
DATA
$domaininfo =~ m/Name servers:\n(\S+)\s+(\S+)/m;
print "Server name = $1\n";
print "IP Address = $2\n";
Now, I can match the \n at the end of the Name servers: line and capture the name and IP address which is on the next line.
This might have to be munged a bit to get it to work in your situation.
This is half a question and perhaps half an answer (the question's in here as I am not yet allowed to write comments...). Okay, here we go:
Name servers:
ns.mistral.co.uk 195.184.229.229
Is this what an entry in the file you're parsing looks like? What will follow immediately afterwards - more domain names and IP addresses? And will there be blank lines in between?
Anyway, I think your problem may (in part?) be related to your reading the file line by line. Once you get to the IP address line, the info about 'Name servers:' having been present will be gone. Multiline matching will not help if you're looking at your file line by line. Thus I'd recommend switching to paragraph mode:
{
local $/ = ''; # one paragraph instead of one line constitutes a record
while ($record = <DOMAINS>) {
# $record will now contain all consecutive lines that were NOT separated
# by blank lines; once there are >= 1 blank lines $record will have a
# new value
# do stuff, e.g. pattern matching
}
}
But then you said
I have tried an example of Stackoverflow where
<DOMAINS>;
will take the next line but this didn't work for me and I assume it is because we have already read the contents of this into $domaininfo.
so maybe you've already tried what I have just suggested? An alternative would be to just add another variable ($indicator or whatever) which you'll set to 1 once 'Name servers:' has been read, and as long as it's equal to 1 all following lines will be treated as containing the data you need. Whether this is feasible, however, depends on you always knowing what else your data file contains.
I hope something in here has been helpful to you. If there are any questions, please ask :)