Powershell - Select a specific word from text - powershell

I'm still very much learning Powershell and I'm a bit lost regarding a command to use.
I have this
docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com
and I want to select PASSWORD.
Ideally, I would like this PASSWORD to get into a file, and use it after (but that I can do).
I am lost on what command to use. I know awk '{print $6}' would work but I need the powershell as I'm using a windows machine.
I know it's a really simple question, I have been reading answers, but I am just confused by the different parameters, and the different ways by different people and well, Powershell is wonderful but I'm still learning.
Thanks a lot!!

The default field separator(s) in awk is whitespace, so we can do the same in PowerShell and then grab the 6th resulting substring.
For this, we can use the -split regex operator - it supports the following syntaxes:
[strings] -split [pattern]
or
-split [strings]
When used as in the second example above, it defaults to splitting on whitespace just like awk:
-split "docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com"
If we wrap the expression in #(), we can index into it:
$Password = #(
-split "docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com"
)[5]
or we can use the Select-Object cmdlet to grab it:
$Password = -split "docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com" |Select-Object -Index 5
If, however, we always want to grab the substring immediately after -p instead of whatever the 6th string is, we could use the -replace regex operator instead:
$string = "docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com"
$string -replace '^.*-p\s+(\S+).*$','$1'

You can make this more complex :) I just used simple regexp, but you can make it better :)
$x = "docker login -u AWS -p PApSSWORD -e none number.dkr.ecr.REGION.amazonaws.com "
$x -match "(\-p[a-z0-9 ]*\-e)"
$matches[1] -replace '(\-p) ([a-z0-9 ]*) (\-e)' , ' $2'

Another solution using a Regular Expression,
here with lookarounds
$string = 'docker login -u AWS -p PASSWORD -e none number.dkr.ecr.REGION.amazonaws.com'
if ($string -match '(?<=-p\s+).*(?=\s+-e)'){
$Password = $Matches.Value
} else {
"No password found"
}

Related

How do I convert a Binary .SQL file into readable text?

Let's say that I have backed up a Database in SQL from a format that sends all Tables to individual .SQL files. They're encrypted / converted to Binary in such a way that makes them very painful to read anything.
The command to export these are in a batch file with this as the producing command:
sqlcmd -S "%DB%,%PORT%" -d "%DBNAME%" -U %DBID% -P %DBPASSWORD% -Q "set nocount on;SELECT name FROM sys.tables order by name;" -h -1 -o table.txt
Followed by:
bcp.exe %DBNAME%.dbo.%%a out %%a.sql -S "%DB%,%PORT%" -n -U %DBID% -P %DBPASSWORD%
Conversely, the command to Import these files is:
bcp.exe %DBNAME%.dbo.%TableName% in %TableName%.sql -S "%HOST_IP%,%PORT%" -T -E -n 1
The problem is - these scripts are executed on the PC Hosting the Database - one that neither I nor my colleagues will always have access to. The purpose of trying to get some of the values out of the raw .SQL files into plain text is to provide some information as a 'checksum' to validate some of the information found within the files without the need of hosting SQL on our local machines.
With this, some of the words are almost plaintext . . . almost. Using a VERY cumbersome method I can get most of the values, but I'm curious to know if there's a more native way to do this very thing. . . .
Unfortunately, SSMS and other sqlcmd or bcp commands won't work (to my knowledge?) without having SQL / SSMS installed on our local machines. . . .
Example of some of the Binary output:
Here is some of the code from before. Basically I'm taking the hex equivalents of the binary characters and replacing them with plain text and then parsing them out with different -replace commands (still a little uglier than I like, but I'm getting an output I can actually use. . .).
$PSFindStr_0='\x12' #DC2#
$PSFindStr_1='\x14' #DC4#
$PSFindStr_2='\x13' #DC3#
$PSFindStr_3='\x0c' #FF#
$PSFindStr0='\x00'
$File = C:\Foo.sql
$OutFile= C:\Foo.txt
$Finding = $PSFindStr_0
$Repl="`r`n#DCTWO#"
$fil2Parse=[IO.File]::ReadAllText($File)
$filparsed=$fil2parse -replace $Finding, $Repl
$Finding = $PSFindStr_1
$Repl="`r`n#DCFOUR#"
$fil2Parse=$filparsed
$filparsed=$fil2parse -replace $Finding, $Repl
$Finding = $PSFindStr_2
$Repl="`r`n#DCTHREE#"
$fil2Parse=$filparsed
$filparsed=$fil2parse -replace $Finding, $Repl
$Finding = $PSFindStr_3
$Repl="`r`n#FF#"
$fil2Parse=$filparsed
$filparsed=$fil2parse -replace $Finding, $Repl
$Finding = $PSFindStr0
$Repl=''
$fil2Parse=$filparsed
$filparsed=$fil2parse -replace $Finding, $Repl
[IO.File]::WriteAllText($OutFile, $filparsed, [System.Text.ASCIIEncoding]::ASCII)
Get-Content $OutFile | Sort-Object -Unique |Set-Content $OutFile
The extended version of the code snip above gives me an output similar to what's below, but the question remains - is there a better way without having to install MSSQL?
ADAM
ADAMO
BENJAMINA
BLAKET
BRIARS
BRIARSKATERINEJ

Passing piped commands via SSH

I'm using the Powershell module Posh-SSH to ssh into an Ubuntu server and run commands. I'm not having any difficulty passing simple lines such as:
$sshSession = New-SSHSession -ComputerName server001 -Credential $credential
$sshStream = New-SSHShellStream -Index $sshSession.sessionID
$sshStream.WriteLine("history")
$sshStream.Read()
The last line outputs exactly what it's supposed to. I want to run the following on the server:
for guest in `nova list --all-tenants --host serverName | grep Shutdown | awk '{ print $2 }'`; do nova start $guest; sleep 5; done"
Pasting this line right into $sshStream.WriteLine("") doesn't work at all as ` is an escape character in Powershell and $'s are used for variables already. I attempted to work around this by escaping some characters and putting it into a variable:
$block = "for guest in ``nova list --all-tenants --host server001 | grep Shutdown | awk '{ print `$2 }'`; do nova start `$guest; sleep 5; done"
$sshStream.WriteLine("$block")
$sshStream.WriteLine($block)
Both of my attempts above do not get read properly on the server. Any idea how I can work around this or if there's a better way to do this?
Thanks in advance
As TessellatingHeckler suggested, I used single-quotes and it worked:
$block = 'for guest in `nova list --all-tenants | grep Shutdown | awk ''{ print $2 }''`; do nova stop $guest; done'
$sshStream.WriteLine($block)
Try this
$block = #"
for guest in ``nova list --all-tenants --host server001 | grep Shutdown | awk '{ print `$2 }'`; do nova start `$guest; sleep 5; done
"#
$sshStream.WriteLine($block)
It will treat the "block" as a literal string (i.e. no escaping).

Differences in calling CSVDE from Powershell vs Command Prompt

Can anyone explain why calling the CSVDE utility from an elevated Windows command prompt would differ than using the same string from an elevated Powershell console? The issue I have is that I can successfully export from Active Directory via the command prompt method, but Powershell returns an authentication error, "Simple bind returned 'Invalid Credentials'.
Here is the command used for both, edited for sensitive pieces:
c:\csvde.exe -s domain.company.org -f ExportFile.csv -l "givenName,sn,ipPhone,title,department,company,physicalDeliveryOfficeName,mail" -d "OU=ABC Group,OU=ABC Users,DC=DomainName,DC=org" -a UserDistinguishedName Password
Both sessions are running with Administrator privileges. I am a Powershell novice, and for the life of me, I can't figure this out.
Thanks!
I can see two potential issues. First thought is that it is taking your user name and password as separate arguments, or as Adi Inbar suggested: you've got some special characters that are causing issues. Either way I'd enclose things in single quotes so that arguments are passed as expected, and taken literally.
c:\csvde.exe -s 'domain.company.org' -f 'ExportFile.csv' -l 'givenName,sn,ipPhone,title,department,company,physicalDeliveryOfficeName,mail' -d 'OU=ABC Group,OU=ABC Users,DC=DomainName,DC=org' -a 'UserDistinguishedName' 'Password'
See if that doesn't resolve the issue. In my experience that is usually a safe way to run a executable from PowerShell. I suppose alternatively you can assign them to variables, and then pass those.
$Server = 'domain.company.org'
$OutFile = 'ExportFile.csv'
$Attributes = 'givenName,sn,ipPhone,title,department,company,physicalDeliveryOfficeName,mail'
$SearchRoot = 'OU=ABC Group,OU=ABC Users,DC=DomainName,DC=org'
$UserID = 'CN=TMTech,OU=Users,DC=Some,DC=Company,DC=org'
$Password = 'P#$$w0rd'
CSVDE.exe -s $Server -f $OutFile -l $Attributes -d $SearchRoot -a $UserID $Password

Perl Syntax Error: bareword found where operator expected

This is my perl script code. in this i'm getting error like "bareword found where operator expected at $cmd"
my $path = $folder."/".$host."_".$database_name.".bak";
$cmd .= "-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" ";
any one help me?
When a string has double quotes within it, you need to escape them with \.
$cmd .= "-U $user_name -P $password -S $host -d master -Q \"BACKUP DATABASE [$database_name] TO DISK = N'$path'\" ";
Also, Perl lets you use other characters for quote delimiters. qq followed by almost any character is the same as double quotes. So you could do things like this to avoid the need of backslashes:
$cmd .= qq(-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" );
$cmd .= qq|-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" |;
And so on...
Update: How to execute a system command in Perl. There are three basic ways:
system($cmd); #Goes through the shell if shell metacharacters are detected.
system(#command_and_args); #first element is the command, the rest are arguments
system executes a command and waits for it to return. The return value is the exit status of the program.
my #results = `$cmd`; #Always goes through shell.
Backticks execute a command and return its output. You should only use this if you actually need the output; otherwise, it is better to go with system.
exec $cmd;
exec #command_and_args;
exec is exactly like system, except that it never returns. It effectively ends your program by calling another program.
Use the one that is most appropriate to your situation. Or in this case, since you are executing SQL, consider using the DBI module. It's definitely a better approach for anything more than a couple of simple commands.
Looks like you have your " characters in the wrong place. I'm not sure where they should be.
In your second line, the string literal:
"-U $user_name -P $password -S $host -d master -Q "
is immediately followed by the bareword
BACKUP

Pulling hostname from TNS entry

I am working on a script that will need to determine which node a db being used by a local app is running on. I've been trying to use this as a chance to force myself to learn awk/sed and have a test script to test the statements. It's working off a copy of the tnsnames.ora file I have moved to the home folder the script is located in.
Here is a valid tnsnames.ora stanza:
(
DESCRIPTION = (
ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=iplab)(Port=1521))
)
(CONNECT_DATA=(SID=spurs1))
)
After doing some research and getting the awk expression to pull the tns entry to $host I came up with the below script but it doesn't seem to work.
#!/bin/ksh
db=spurs
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo $host
host= $host | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/'
echo $host
When I run it the awk statement I get the following:
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
./tns.ksh: line 6: (DESCRIPTION: not found
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
From what I have seen reading tutorials and forums I think sed is setup correctly and should be setting $host to one or more lowercase letters followed by 0 or 1 numbers after Host = . Since (DESCRIPTION is the start of $host before and after the sed statement I'm not sure how it isn't finding it, an
This worked for me:
tnsping $db | grep HOST | cut -d\ -f 14 | sed 's/).*//g'
On my system I can use this to get the host as long as the host name doesn't have an equals sign (or the actual literal word HOST in the name of the host):
echo $TNS_STRING | sed 's/.HOST//g' | sed 's/).//g' | sed 's/=//g' | sed 's/\s*//g'
Your value for $host is likely a multiline value, so you need to quote it anyplace you use it, i.e.
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo "$host"
You also need to capture the output (using command-substitution) via $(...)
host=$(echo "$host" | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/')
echo "$host"
(and echo it), so it can be processed by sed
Revise
host=$(echo $host | sed 's/.*Host=//; s/).*$//)
echo "$host"
I've switched back to just $host, without the dbl-quotes, as you don't want the linebreaks in the data. Now it is all one big string, and the regex, strips every upto host=, and then strips everything after the first remaining ) char.
If you still get error messages, I don't have access to a tnsnames.ora record, so please edit your query to include a valid record.
I hope this helps.
you may be better relying on the output of tnsping instead of parsing the file: tnsping appears to emit the description on one line:
host=$(
tnsping $db | while read line; do
if [[ "$line" == *HOST* ]]; then
s=${line#*HOST=}; s=${s%%)*}; echo "$s"; break
fi
done
)
This might work for you:
db=spurs
host=$(sed '/^(/,/^)/!d;/^(/{h;d};H;/^)/!d;g;/'"$db"'/!d;s/.*Host=\([^)]*\).*/\1/' tnsnames.ora)
Tested Code:
OIFS=$IFS;
IFS="(";
tns=`tnsping TNS_ALIAS`
tns_arr=($tns);
tns_info=(`(for ((i=0; i<${#tns_arr[#]}; ++i)); do echo "${tns_arr[$i]/)/}"; done)| grep 'HOST\|PORT'|sed 's/)//g'|sed 's/ //g'`)
for ((i=0; i<${#tns_info[#]}; ++i)); do eval "export ${tns_info[$i]}"; done
echo "host:" $HOST
echo "port:" $PORT
IFS=$OIFS;