Cuma Eğlencesi - PowerShell Saçmalık Mücadelesi
Bugün PowerShell çözümümü yakın zamanda gerçekleşen bir Iron Scripter mücadelesinde paylaşmayı düşündüm. Buradaki zorluk, anlamsız kelimelerle dolu 10 örnek dosya oluşturma hedefiyle anlamsız belgeler oluşturacak PowerShell kodunu oluşturmaktı. Evet, bazı test dosyalarının üzerinde çalışmasını istemek dışında, ilk bakışta bu zorluk anlamsız görünüyor. Ancak tüm bu zorluklarda ve hatta The PowerShell Practice Primer'daki zorluklarda olduğu gibi yolculuk ödüldür. Gerçek değer, PowerShell'in nasıl kullanılacağını öğrenmek ve belki de yeni bir teknik veya komut keşfetmektir. Umudumuz, bu zorluk üzerinde çalışırken PowerShell komut dosyası yazma becerilerinizi geliştirmenizdir. Ve kim bilir, belki de yol boyunca biraz eğlenebiliriz.
Saçma Belgeler
Her şeyi Github'daki PSNonsense adlı bir modüle koydum.
Buna yapı taşı yaklaşımıyla yaklaştım. Anlamsız bir kelime yaratmak için bir fonksiyonla başlıyorum. Bu yeterince basit. Tek yapmam gereken bir havuzdan rastgele birkaç karakter seçip onları bir araya getirmek.
$letters = [Char[]]'abcdefghijklmnopqrstuvwxyz'
#add some diacritical characters
$letters += [Char]0x00EB,[Char]0x00E4,[Char]0x00E9
-join ( $letters | Get-Random -count $Length)
İşlev, tüm işlevler gibi, rastgele bir varsayılanı kullanarak uzunluğu veya sayımı tanımlamak için parametreler içerir. Ayrıca kullanıcının girebileceği parametre değerini doğrulamak için ValidateSet niteliğini de kullanıyorum.
Param(
[Parameter(Position = 0, HelpMessage = "Indicate the word length between 1 and 10.")]
[ValidateRange(1, 10)]
[int]$Length = (Get-Random -Minimum 1 -Maximum 10)
)Anlamsız bir kelime yaratmak bu kadar kolaydır.
PS C:\> New-NonsenseWord -Length 7
ëfswäna
Saçma bir cümle, saçma kelimelerin bir araya gelmesinden ibarettir. Ancak noktalama işareti ekleme ve cümlelerin noktayla bitmesini sağlama konusunda ek bir zorluk daha vardı. Bazı cümleleri soru işareti veya ünlem işaretiyle rastgele sonlandıracak kod ekledim.
$punct = ", ", "; ", " - ", ": "
#define a flag to indicate if random punctuation has been inserted.
$NoPunct = $true
1..($WordCount - 1) | ForEach-Object -Begin {
#make sure we start the sentence with a word
[string]$sentence = New-NonsenseWord
} -process {
#insert random punctuation into the sentence, but only once
if (($WordCount -ge 10) -AND (Test) -AND $NoPunct) {
$sentence += $punct | Get-Random -Count 1
$NoPunct = $False
}
$sentence += "{0} " -f (New-NonsenseWord)
}
#capitalize the first word of the sentence.
#does the sentence end in a period, exclamation or question mark.
#The period should be the default most of the time
$rn = Get-Random -Maximum 100 -Minimum 1
Switch ($rn) {
{$_ -ge 90} {$end = "?" ; break}
{$_ -ge 82} { $end = "!"}
Default { $end = "."}
}
$out = "{0}{1}{2}" -f ([string]$sentence[0]).ToUpper(), $sentence.substring(1).TrimEnd(),$end
İşlev, noktalama işareti eklemek gibi bir şey yapmam gerekip gerekmediğini rastgele belirleyen Test adında özel bir işlev içerir.
PS C:\> New-NonsenseSentence -WordCount 11
Urip; élthe qkvipwen kym h fäuq cwuoéhjnä ikafysqol eom ikäb yke.Paragraf oluşturmak, belirli sayıda cümleyi bir araya getirmek anlamına gelir.
$raw = 1..$SentenceCount | Foreach-object {New-NonsenseSentence}
($raw -join " ").trimend()
Örnekler biraz uzadığı için işte bir ekran görüntüsü.
Noktalama işaretlerine dikkat edin.
Bir belge oluşturmak paragraflardan oluşan bir koleksiyondan başka bir şey değildir.
#insert a return after each paragraph
1..$ParagraphCount | ForEach-Object {New-NonsenseParagraph;"`r"}
Bu New-NonsenseDocument fonksiyonu ile 10 adet doküman oluşturmak için buna benzer bir kod kullanabilirim.
1..10 | ForEach-Object {
$filename = [System.IO.Path]::GetRandomFileName()
#replace the extension
$filename = $filename -replace "\.\w+", ".txt"
#build the path
$path = Join-Path -path $env:TEMP -ChildPath $filename
#create the document
#encode as UTF8 to save the diacritical characters
New-NonsenseDocument -ParagraphCount (Get-Random -Minimum 3 -Maximum 10) |
Out-File -FilePath $path -Encoding utf8
#view the result
Get-Item $path
}Rastgele bir dosya adı oluşturmak için .NET Framework'ü kullanıyorum ve ardından uzantıyı .txt uzantısıyla değiştirmek için bir regex modeli kullanıyorum. Son dosya yolu, dizeleri bir araya getirmeye çalışmak yerine önerilen Birleştirme Yolu kullanılarak oluşturulur. Dosyaları PSNonsense deposundaki Örnekler klasöründe görüntüleyebilirsiniz.
Markdown Saçmalığı
Bu zorluğun saçma bir indirim belgesi oluşturmak için ekstra kredi gereksinimi vardı. Bir işaretleme belgesinin başlıklar için özel gereksinimleri vardır. Sonuçta dosyayı bir here-string kullanarak ve rastgele oluşturulmuş işaretleme elemanları ekleyerek oluşturdum.
İşleri basitleştirmek için (dürüst olmak gerekirse), PSNonsense komutlarını birkaç yardımcı veya hileci işleve ekledim.
function New-Heading {
(New-NonsenseSentence -WordCount (Get-Random -Minimum 1 -Maximum 5)) -replace "[.!?]", ""
}
function New-CodeFence {
$cmd = "$((New-NonsenseSentence -WordCount (Get-Random -Minimum 2 -Maximum 6)) -replace "[.!?]",'')"
#the backtick needs to be escaped so that end result is a proper markdown code fence.
#there should be 6 backticks.
$cf = @"
$('`'*6)powershell
PS C:\> $cmd
$('`'*6)
"@
$cf
}
function New-SubHead {
Param(
[int]$Level = 2
)
$h = "#"*$level
$head = "{0} {1}" -f $h, (New-Heading)
#write-host $head -ForegroundColor red
$out = @"
$head
"@
1..(Get-Random -Maximum 4) | ForEach-Object {
$p = (New-NonsenseParagraph -SentenceCount (Get-Random -Minimum 4 -Maximum 10) -outvariable pv)
if ((Get-Random)%3) {
#randomly format a string
$wds = ($p.split()).where( {$_ -match "\w+"})
$hl = $wds | Select-Object -skip (Get-Random -Minimum 7 -Maximum ($wds.count - 20)) -First (Get-Random -Minimum 1 -Maximum 7)
#randomly decide how to format
Switch ((Get-Random)) {
{$_%3} {$f = "*$($hl -join " ")*" }
{$_%5} {$f = "__$($hl -join " ")__"}
{$_%7} {$f = "__*$($hl -join " ")*__" }
{$_%4} {$f = "``$($hl -join " ")``" }
{$_%2} {$f = "[$($hl -join " ")](https://www.$(New-NonsenseWord).com)"}
}
#left justify to send to the here string to avoid extra spaces
$out += ($p -replace ($hl -join " "), $f)
} #if %3
else {
$out += $p
}
$out += "`n`n"
<#
the out variable is itself an array. I want to get the first item in that array,
which will be a string and then the first character in that string.
#>
if ($pv[0][0] -match "[aeifuylm]") {
#$out+="`n"
#increment if the next level is 4 or less
if ($level + 1 -le 4) {
$out += New-SubHead -level ($level + 1)
}
else {
#repeat the level
$out += New-SubHead -level $level
}
}
elseif ($pv[0][0] -match "[pjqrst]" ) {
$out += New-CodeFence
$out += "`n`n"
#add a bit more verbiage
$out += New-NonsenseParagraph -SentenceCount (Get-Random -Minimum 1 -Maximum 4)
}
} #foreach object
$out
} #New-SubHeadRastgele kod çit bölümleri ekleyerek ve rastgele ifadeleri biçimlendirerek kendime daha da fazla meydan okudum. Fonksiyonlardaki yorumların düşünce sürecimi açıkladığını düşünüyorum. Bu işlevlerle ve PSNonsense modülümle saçma bir işaretleme belgesi oluşturmak için bunun gibi bir kod çalıştırabilirim.
$md = @"
# $(New-Heading)
$((New-SubHead).trimend())
__My additional New-Headings follow.__
"@
1..(Get-Random -maximum 5) | ForEach-Object {
$md += New-SubHead
}
$md += "Updated *$(Get-Date)*."
$md
#encode as UTF8 to save the diacritical characters
$md | Out-File -FilePath c:\work\nonsense.md -Encoding utf8
Buradaki dizeler, uygun bir işaretleme belgesi oluşturmak için gerekli boş satırları içerir. Dosya kodlamasıyla ilgili mesajı not edin. Özel karakterler kullanırsanız ve UTF8 belirtmezseniz dosyada '?' karakterleri bulunabilir. VS Code'da fark ettiğim şeylerden biri editör modunda işaretleme belgesinin iyi olmasıdır. Ancak önizleme modunu kullandığımda özel karakterleri algılamıyor. Bug mı yoksa henüz bulamadığım bir ayar mı bilemiyorum. Ne olursa olsun, saçma sapan işaretlememi ve PDF sürümünü Github'daki Örnekler klasöründe bulabilirsiniz.
Umarım modülün deposundaki koda bakmak için biraz zaman ayırırsınız. İdeal olarak, nasıl çalıştığını ve nedenini görmek için kendiniz deneyeceksiniz. Yeni bir şey öğrenirsen umarım bana haber verirsin.
Bu arada PowerShell'i her gün kullanmaya devam edin. Eğer yapmadıysanız, https://ironscripter.us adresindeki diğer kodlama zorluklarına göz atın ve bunları çözmek için şansınızı deneyin. Herhangi bir süre sınırı veya son kullanma tarihi yoktur ve öğrendiklerinize şaşırabilirsiniz.
