String variable position being overwritten in write-host - powershell

If I run the below code, $SRN can be written as output or added to another variable, but trying to include either another variable or regular text causes it to be overwritten from the beginning of the line. I'm assuming it's something to do with how I'm assigning $autocode and $SRN initially but can't tell what it's trying to do.
# Load the property set to allow us to get to the email body.
$item.load($psPropertySet) # Load the data.
$bod = ($item.Body.Text -creplace '(?m)^\s*\r?\n','') -split "\n" # Get the body text, remove blank lines, split on line breaks to create an array (otherwise it is a single string).
$autocode = $bod[4].split('-')[2] # Get line 4 (should be Title), split on dash, look for 3rd element, this should contain our automation code.
$SRN = $bod[1] -replace 'ID: ','' # Get line 2 (should be ID), find and replace the preceding text.
# Skip processing if autocode does not match our list of handled ones.
if ($autocode -cin $autocodes)
{
write-host "$SRN $autocode"
write-host "$autocode $SRN"
write-host "$SRN test"
$var = "$SRN $autocode"
$var
}
The code results in this, you can see if $SRN isn't at the start of the line it is fine. Unsure where the extra spaces come from either:
KRNE8385
KRNE SR1788385
test8385
KRNE8385
I would expect to see this:
SR1788385 KRNE
KRNE SR1788385
SR1788385 test
SR1788385 KRNE

LotPings pointed me down the right path, both variables still had either "0D" or "\r" in them. My regex replace was only getting rid of them on blank lines, and I split the array on "\n" only. Changing line 3 in the original code to the below appears to have resolved the issue. First time seeing Format-Hex, but it appears to be excellent for troubleshooting such issues.
$bod = ($item.Body.Text -creplace '(?m)^\s*\r?\n','') -split "\r\n"

Related

Powershell Parse Response String of Requirements.txt file

Been struggling for a few hours. I'm trying to hit this link
That has these contents:
# Generated on: Python 3.6.12
# With snowflake-connector-python version: 2.4.6
asn1crypto==1.4.0
azure-common==1.1.27
azure-core==1.15.0
azure-storage-blob==12.8.1
boto3==1.17.98
botocore==1.20.98
certifi==2021.5.30
cffi==1.14.5
chardet==4.0.0
cryptography==3.4.7
dataclasses==0.8
idna==2.10
isodate==0.6.0
jmespath==0.10.0
msrest==0.6.21
oauthlib==3.1.1
oscrypto==1.2.1
pycparser==2.20
pycryptodomex==3.10.1
PyJWT==2.1.0
pyOpenSSL==20.0.1
python-dateutil==2.8.1
pytz==2021.1
requests==2.25.1
requests-oauthlib==1.3.0
s3transfer==0.4.2
six==1.16.0
urllib3==1.26.5
And pass each non-commented out line to Poetry (a command line tool for Python dependency management)
This is my first step
(iwr https://raw.githubusercontent.com/snowflakedb/snowflake-connector-python/v2.5.1/tested_requirements/requirements_36.reqs | Select-Object).Content > req.txt
Where I'm struggling is I've tried doing convertfrom-string with various delimiters, and .Split(), and I can't seem to parse out the pieces I need. Poetry needs to take as input just the "packagename==" although version number is optional. So I essentially want to ignore lines that start with a "#" and then pass each line through a pipe, or even save it as an array. It doesn't seem to respond to setting a delimited to "\t" or carriage return "`r".
So next I would do something like
foreach($package in $package_array){poetry add $package}
Any help would be appreciated.
AdminOfThings provided a good pointer in a comment, but let me try to put it all together:
$url = 'https://raw.githubusercontent.com/snowflakedb/snowflake-connector-python/v2.5.1/tested_requirements/requirements_36.reqs'
foreach ($pkgLine in (irm $url).Trim() -split '\r?\n' -notmatch '^\s*#') {
# Remove `Write-Host` to perform the actual poetry call.
Write-Host poetry add ($pkgLine -replace '=.*')
}
irm is the built-in alias for Invoke-RestMethod, which is a simpler alternative to Invoke-WebRequest (iwr) in this case, because it directly returns the text of interest, as a multi-line string.
As an aside: the | Select-Object in your code is effectively a no-op and can be omitted.
.Trim() trims a trailing newline (all trailing whitespace).
-split '\r?\n' splits the string into individual lines.
-notmatch '^\s*# filters out all lines that start with #, optionally preceded by whitespace.
-replace '=.* removes everything starting with = from each package line.

Replace first two characters of each line of a file via PowerShell

I have a file that needs to have the first two characters of each line replaced. It seems easy but those same first two characters "|0" showup elsewhere in the file. So I've ended up having the replacement strings "$bp" all over the place. Any way to just replace the first instance of "|0" for each line only? Here is the sample data:
0|Corrupt Record|0|0|0|0|0|0|0|0|0
Your question is unclear (|0 vs 0|).
You can use this snippet to replace the 2 first characters of each line if they are 0|:
$oldContent = Get-Content "my/file"
$newContent = $OldContent | ForEach-Object { $_ -replace "^0\|","newstring" }
# simpler
#$newContent = $OldContent -replace "^0\|","newstring"
$newContent | Set-Content "my/file"
I'm sure there are other ways to do this, but here is how my approach would be.
To replace just the first occurrence of "0|" and have the remaining stay you can replace it like so.
$CorruptString = "0|Corrupt Record|0|0|0|0|0|0|0|0|0"
[regex]$ToReplace = "0\|"
$ToReplace.replace($CorruptString, "", 1)
This will Output:
Corrupt Record|0|0|0|0|0|0|0|0|0
Just a simple regex to replace the corrupt string and replace it with either nothing or whatever you wanted to replace it with. Naturally the 1 is so it only does it one time.
I believe that is what you were looking for. If not try to explain more.
EDIT: because there was some confusion with the post. To replace the first two characters in a string you can just do substring to remove the first two.
"0|Corrupt Record|0|0|0|0|0|0|0|0|0".Substring(2)

powershell - replace line in .txt file

I am using PowerShell and I need replace a line in a .txt file.
The .txt file always has different number at the end of the line.
For example:
...............................txt (first)....................................
appversion= 10.10.1
............................txt (a second time)................................
appversion= 10.10.2
...............................txt (third)...................................
appversion= 10.10.5
I need to replace appversion + number behind it (the number is always different). I have set the required value in variable.
How do I do this?
Part of this issue you are getting, which I see from your comments, is that you are trying to replace text in a file and saved it back to the same file while you are still reading it.
I will try to show a similar solution while addressing this. Again we are going to use -replaces functionality as an array operator.
$NewVersion = "Awesome"
$filecontent = Get-Content C:\temp\file.txt
$filecontent -replace '(^appversion=.*\.).*',"`$1$NewVersion" | Set-Content C:\temp\file.txt
This regex will match lines starting with "appversion=" and everything up until the last period. Since we are storing the text in memory we can write it back to the same file. Change $NewVersion to a number ... unless that is your versioning structure.
Not sure about what numbers you are keeping
About which part of the numbers, if any, you are trying to preserve. If you intend to change the whole number then you can just .*\. to a space. That way you ignore everything after the equal sign.
Yes, you can with regex.
Let call $myString and $verNumber the variables with text and version number
$myString = "appversion= 10.10.1";
$verNumber = 7;
You can use -replace operator to get the version part and replace only last subversion number this way
$mystring -replace 'appversion= (\d+).(\d+).(\d+)', "appversion= `$1.`$2.$verNumber";

Powershell break a file up on character count

I have a binary file that I need to process, but it contains no line breaks in it.
The data is arranged, within the file, into 104 character blocks and then divided into its various fields by character count alone (no delimiting characters).
I'd like to firstly process the file, so that there is a line break (`n) every 104 characters, but after much web searching and a lot of disappointment, I've found nothing useful yet. (Unless I ditch PowerShell and use awk.)
Is there a Split option that understands character counts?
Not only would it allow me to create the file with nice easy to read lines of 104 chars, but it would also allow me to then split these lines into their component fields.
Can anyone help please, without *nix options?
Cheers :)
$s = get-content YourFileName | Out-String
$a = $s.ToCharArray()
$a[0..103] # will return an array of first 104 chars
You can get your string back the following way, the replace removes space char( which is what array element separators turn into)
$ns = ([string]$a[0..103]).replace(" ","")
Using the V4 Where method with Split option:
$text = 'abcdefghi'
While ($text)
{
$x,$text = ([char[]]$text).where({$_},'Split',3)
$x -join ''
}
abc
def
ghi

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 :)