Minden, amit tudni szeretne a sztringek változóinak helyettesítéséről

A változók számos módon használhatók sztringekben. Változók helyettesítésének nevezem ezt, de arra gondolok, amikor egy sztringet formázni szeretne úgy, hogy a változók értékei is belekerüljenek. Ez olyasmi, amit gyakran találok magamat magyarázni új szkriptereknek.

Megjegyzés

A cikk eredeti verziója@KevinMarquette blogján jelent meg. A PowerShell csapata köszönjük Kevinnek, hogy megosztotta velünk ezt a tartalmat. Kérjük, látogasd meg a blogot a PowerShellExplained.comoldalon.

Összeláncolás

A metódusok első osztályát összefűzésnek is nevezhetjük. Alapvetően több karakterláncot vesz, és összekapcsolja őket. A formázott karakterláncok összeállításához az összefűzés hosszú múltra tekint vissza.

$name = 'Kevin Marquette'
$message = 'Hello, ' + $name

Az összefűzés akkor működik jól, ha csak néhány értéket kell hozzáadni. De ez gyorsan bonyolulttá teheti.

$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'

Ez az egyszerű példa már egyre nehezebben olvasható.

Változó helyettesítése

A PowerShell egy másik, egyszerűbb lehetőséggel is rendelkezik. A változókat közvetlenül a sztringekben adhatja meg.

$message = "Hello, $first $last."

A sztring körül használt idézőjelek típusa különbséget tesz. A kettős idézőjeles karakterlánc lehetővé teszi a helyettesítést, de egyszeres idézőjeles karakterlánc nem. Vannak olyan esetek, amikor az egyiket vagy a másikat szeretné, ezért van lehetősége.

Parancsok helyettesítése

A dolgok kissé bonyolulttá válnak, amikor megpróbálja a tulajdonságok értékeit egy sztringbe helyezni. Itt sok új ember zavarba jön. Először hadd mutassam meg, szerintük mi működhetne (és első ránézésre szinte úgy néz ki, mintha működnie kellene).

$directory = Get-Item 'C:\windows'
$message = "Time: $directory.CreationTime"

Azt várná, hogy eltávolítja a CreationTime-t a $directory-ről, de ehelyett ezt a Time: C:\windows.CreationTime kapja értékként. Ennek az az oka, hogy az ilyen típusú helyettesítés csak az alapváltozót látja. Az időszakot a sztring részeként tekinti, így nem oldja fel mélyebben az értéket.

Ez csak úgy történik, hogy ez az objektum egy sztringet ad alapértelmezett értékként egy sztringbe való elhelyezéskor. Egyes objektumok inkább a típusnevet adják meg, például System.Collections.Hashtable: . Csak valami, amit figyelni kell.

A PowerShell lehetővé teszi a parancsok végrehajtását a sztringen belül egy speciális szintaxissal. Így lekérheti ezeknek az objektumoknak a tulajdonságait, és bármilyen más parancsot futtathat egy érték lekéréséhez.

$message = "Time: $($directory.CreationTime)"

Ez bizonyos helyzetekben nagyszerűen működik, de ha csak néhány változó áll rendelkezésére, ugyanolyan bonyolulttá válhat, mint az összefűzés.

Parancs végrehajtása

Parancsokat karakterláncon belül is futtathat. Bár van ilyen lehetőségem, nem tetszik. Gyorsan átláthatatlanná válik, és nehéz hibakeresni. Futtatom a parancsot, és egy változóba mentöm, vagy egy formátumsztringet használok.

$message = "Date: $(Get-Date)"

Sztring formázása

A .NET-nek van egy módja, hogy formázza a sztringeket, amelyekkel elég könnyen dolgozhatok. Először hadd mutassam meg a statikus módszert, mielőtt megmutatom, hogyan lehet ugyanezt elérni a PowerShell gyorsabb megoldásával.

# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)

# PowerShell format string
'Hello, {0} {1}.' -f $first, $last

Itt az történik, hogy a karaktersorozat a tokenek {0} és {1} mentén kerül elemzésre, majd ezt a számot használja a megadott értékek közül való választáshoz. Ha egy értéket meg szeretne ismételni egy helyen a sztringben, újra felhasználhatja ezt az értékszámot.

Minél bonyolultabb a karakterlánc, annál több hasznot húz ebből a megközelítésből.

Értékek formázása tömb formájában

Ha a formátumvonal túl hosszú lesz, először egy tömbbe helyezheti az értékeket.

$values = @(
    "Kevin"
    "Marquette"
)
'Hello, {0} {1}.' -f $values

Ez nem tömbszétbontás, mert az egész tömböt adom át, de a gondolat hasonló.

Speciális formázás

Szándékosan említettem meg ezeket a .NET-ből származónak, mert már jól dokumentált sok formázási lehetőség rajta. A különböző adattípusok formázásának beépített módjai vannak.

"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f  8175133
20211110
Population 8,175,133

Nem fogok részletekbe bocsátkozni, de szerettem volna tudatni Önnel, hogy ez egy nagyon hatékony formázási motor, ha szüksége van rá.

Sztringek összekapcsolása

Néha valóban össze szeretné fűzni az értékek listáját. Van egy -join operátor, aki ezt meg tudja tenni. Lehetővé teszi, hogy megadjon egy karaktert, amely összekapcsolja a sztringeket.

$servers = @(
    'server1'
    'server2'
    'server3'
)

$servers  -join ','

Ha elválasztójel nélküli sztringeket szeretne -join használni, meg kell adnia egy üres sztringet ''. De ha csak erre van szüksége, van egy gyorsabb lehetőség.

[string]::Concat('server1','server2','server3')
[string]::Concat($servers)

Érdemes megemlíteni azt is, hogy karakterláncokat is -split használhat.

Join-Path

Ezt gyakran figyelmen kívül hagyják, de nagyszerű parancsmag egy fájlútvonal létrehozásához.

$folder = 'Temp'
Join-Path -Path 'C:\windows' -ChildPath $folder

Az ebben a nagyszerű, hogy helyesen kezeli a fordított perjeleket, amikor összerakja az értékeket. Ez különösen akkor fontos, ha felhasználóktól vagy konfigurációs fájloktól vesz értékeket.

Ez is jól megy, Split-Path és Test-Path. Én is foglalkozom ezekről a bejegyzésben az olvasással és mentéssel fájlokba.

A karakterláncok tömbök

Mindenképpen meg kell említenem a karakterláncok hozzáadását, mielőtt továbblépnék. Emlékezzen, hogy a karaktersorozat csak egy karaktertömb. Amikor több sztringet összefűz, minden alkalommal létrejön egy új tömb.

Tekintse meg ezt a példát:

$message = "Numbers: "
foreach($number in 1..10000)
{
    $message += " $number"
}

Nagyon egyszerűnek tűnik, de azt nem látja, hogy minden alkalommal, amikor egy sztringet adnak hozzá $message , egy teljesen új sztring jön létre. A rendszer lefoglalja a memóriát, az adatokat átmásolja, a régit pedig elveti. Nem jelent nagy ügyet, ha csak néhányszor történik, de egy ilyen hurok igazán felfedi a problémát.

StringBuilder

A StringBuilder nagy karakterláncok készítéséhez is nagyon népszerű, sok kisebb karakterláncból. Ennek az az oka, hogy csak összegyűjti a hozzá hozzáadott összes sztringet, és csak összefűzi az összeset az érték lekérésekor.

$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"

[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
    [void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()

Ez megint olyasmi, amihez a .NET-hez fordulok. Már nem használom gyakran, de jó tudni, hogy ott van.

Elkülönítés kapcsos zárójelekkel

Ez a sztringen belüli utótag-összefűzéshez használatos. Előfordulhat, hogy a változónak nincs tiszta szóhatára.

$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"

Köszönöm Redditornak u/real_parbold azért.

Íme egy alternatíva a következő megközelítésre:

Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester

Én személy szerint használja formátum sztring erre, de ez jó tudni abban az esetben, ha látja, hogy a vadonban.

Jogkivonatok keresése és cseréje

Bár a legtöbb funkció csökkenti a saját megoldás létrehozásának szükségességét, előfordulhat, hogy vannak nagy sablonfájlok, amelyekben szövegeket szeretne cserélni.

Tegyük fel, hogy sok szöveget tartalmazó fájlból vett be sablont.

$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'

Előfordulhat, hogy sok tokent kell lecserélnie. A trükk egy egyedi jel használata, amely könnyen megtalálható és lecserélhető. Általában egy speciális karaktert használok mindkét végén, hogy megkülönböztessem.

Nemrég találtam egy új módszert a megközelítésre. Úgy döntöttem, hogy itt hagyom ezt a szakaszt, mert ez egy gyakran használt minta.

Több jogkivonat cseréje

Ha rendelkezem egy listával a helyettesítendő elemekről, általánosabb megközelítést alkalmazok. Elhelyezném őket egy kivonatolóban, és iterálnám őket a csere érdekében.

$tokenList = @{
    Full_Name = 'Kevin Marquette'
    Location = 'Orange County'
    State = 'CA'
}

$letter = Get-Content -Path TemplateLetter.txt -RAW
foreach( $token in $tokenList.GetEnumerator() )
{
    $pattern = '#{0}#' -f $token.key
    $letter = $letter -replace $pattern, $token.Value
}

Ezek a tokenek szükség esetén JSON-ból vagy CSV-ből tölthetők be.

ExecutionContext ExpandString

Egy helyettesítő karakterláncot intelligensen definiálhat egyszeres idézőjelekkel, és később kibonthatja a változókat. Tekintse meg ezt a példát:

$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)

Az aktuális végrehajtási környezetben lévő InvokeCommand.ExpandString hívás a helyettesítéshez az aktuális hatókörben lévő változókat használja. A legfontosabb itt az, hogy a $message változók már nagyon korán meghatározhatók, mielőtt a változók léteznének.

Ha csak egy kicsit bővítjük ezt a helyettesítést, ezt a helyettesítést újra és újra elvégezhetjük különböző értékekkel.

$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
    $ExecutionContext.InvokeCommand.ExpandString($message)
}

Hogy folytassa ezt az ötletet; Ehhez importálhat egy nagy méretű e-mail-sablont egy szövegfájlból. Meg kell köszönnöm Mark Krausnak ezt a javaslatot.

Bármi is működik a legjobban az Ön számára

Én vagyok a rajongója a formátum sztring megközelítés. Határozottan ezt csinálom a bonyolultabb sztringekkel, vagy ha több változó van. Bármire, ami nagyon rövid, bármelyiket használhatom.

Bármi egyéb?

Sok mindent átfogtam ezen a témán. Remélem, hogy elsétálsz valami újat tanulni.

Ha többet szeretne megtudni a sztringinterpolációt lehetővé tevő módszerekről és funkciókról, tekintse meg a referenciadokumentáció alábbi listáját.