다음을 통해 공유


문자열의 변수 대체에 대해 알고 싶은 모든 것

문자열에서는 다양한 방법으로 변수를 사용할 수 있습니다. 이 변수 대체를 호출하지만 변수의 값을 포함하도록 문자열의 서식을 지정하려는 경우를 참조합니다. 이것은 내가 종종 새로운 스크립터에게 설명하는 자신을 찾을 수있는 무언가이다.

참고 항목

현재 문서의 원본 버전@KevinMarquette가 작성한 블로그에 있습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com에 있는 그의 블로그를 확인하세요.

Concatenation

메서드의 첫 번째 클래스를 연결이라고 합니다. 기본적으로 여러 문자열을 가져와 함께 조인합니다. 연결은 아주 오랫동안 서식이 지정된 문자열을 작성하는 용도로 사용했습니다.

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

추가할 값이 몇 가지만 있는 경우 연결이 정상으로 작동합니다. 하지만 이렇게 되면 머지않아 복잡해질 것입니다.

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

이 간단한 예제조차 벌써 읽기가 어려워졌습니다.

변수 대체

PowerShell에는 더 쉬운 다른 옵션이 있습니다. 문자열에서 직접 변수를 지정할 수 있습니다.

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

문자열 주위에 사용하는 따옴표의 형식이 차이를 만듭니다. 큰따옴표로 묶은 문자열은 대체를 허용하지만 따옴표로 묶은 단일 문자열은 허용하지 않습니다. 옵션을 사용할 수 있도록 하나 또는 다른 하나를 원하는 경우가 있습니다.

명령 대체

속성 값을 문자열로 가져오는 작업을 시작하면 상황이 좀 더 복잡해집니다. 이것은 많은 새로운 사람들이 트립 얻을 곳이다. 먼저 그들이 작동해야한다고 생각하는 것을 보여 드리겠습니다 (그리고 액면가는 거의 있어야하는 것처럼 보입니다).

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

당신은 오프$directory를 얻을 것으로 예상 CreationTime 될 것 이다, 하지만 대신 당신은 당신의 값으로 이것을 Time: c:\windows.CreationTime 얻을. 그 이유는 이러한 형식의 대체가 기본 변수만 표시하기 때문입니다. 마침표를 문자열의 일부로 간주하기 때문에 더 깊은 값의 확인을 중지합니다.

이 개체는 문자열에 배치할 때 문자열을 기본값으로 제공합니다. 일부 개체는 다음과 같이 System.Collections.Hashtable형식 이름을 지정합니다. 그냥 뭔가에 대 한 보고.

PowerShell을 사용하면 특수 구문을 사용하여 문자열 내에서 명령 실행을 수행할 수 있습니다. 이렇게 하면 이러한 개체의 속성을 가져와서 다른 명령을 실행하여 값을 가져올 수 있습니다.

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

이는 일부 상황에서는 잘 작동하지만 몇 가지 변수만 있는 경우 연결만큼 미쳐도 됩니다.

명령 실행

문자열 내에서 명령을 실행할 수 있습니다. 나는이 옵션이 있지만, 나는 그것을 좋아하지 않는다. 빠르고 디버깅하기 어려워집니다. 명령을 실행하고 변수에 저장하거나 형식 문자열을 사용합니다.

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

형식 문자열

.NET에서는 대단히 쉬운 방식으로 문자열의 형식을 지정할 수 있습니다. 먼저 동일한 작업을 수행하는 PowerShell 바로 가기를 표시하기 전에 정적 메서드를 보여 드리겠습니다.

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

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

여기서 일어나는 일은 문자열이 토큰 {0} {1}에 대해 구문 분석된 다음, 해당 숫자를 사용하여 제공된 값에서 선택하는 것입니다. 문자열에서 한 값을 반복하려는 경우 해당 값 번호를 다시 사용할 수 있습니다.

문자열이 복잡해질수록 이 접근 방식에서 더 많은 값을 얻을 수 있습니다.

값을 배열로 서식 지정

서식 선이 너무 길면 먼저 배열에 값을 배치할 수 있습니다.

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

전체 배열을 전달하고 있기 때문에 이것은 스플래팅되지 않지만 아이디어는 비슷합니다.

고급 서식 지정

이미 잘 문서화된 많은 서식 옵션이 있기 때문에 의도적으로 .NET에서 오는 것으로 불렀습니다. 다양한 데이터 형식의 형식을 지정하는 기본 제공 방법이 있습니다.

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

나는 그들에 가지 않을거야하지만 난 그냥 당신이 그것을 필요로하는 경우이 매우 강력한 서식 엔진임을 알려주고 싶었다.

문자열 조인

실제로 값 목록을 함께 연결하려는 경우가 있습니다. -join 이 작업을 수행할 수 있는 연산자가 있습니다. 문자열 간에 조인할 문자를 지정할 수도 있습니다.

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

$servers  -join ','

구분 기호 없이 일부 문자열을 -join 사용하려면 빈 문자열 ''을 지정해야 합니다. 하지만 이 작업만 해야 한다면 더 빠른 선택지가 있습니다.

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

또한 문자열도 -split 사용할 수 있다는 점을 지적할 가치가 있습니다.

Join-Path

이는 종종 간과되지만 파일 경로를 빌드하는 데 유용한 cmdlet입니다.

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

이에 대한 좋은 점은 값을 함께 넣을 때 백슬래시를 올바르게 작동한다는 것입니다. 이는 사용자 또는 구성 파일의 값을 가져올 때 특히 중요합니다.

Split-PathTest-Path에서도 아주 잘 작동합니다. 파일 읽기 및 쓰기에 관한 제 포스트에서도 관련 내용을 확인할 수 있습니다.

문자열은 배열입니다.

계속하기 전에 여기에 문자열을 추가하는 것을 언급해야 합니다. 문자열은 단순한 문자 배열임을 잊지 마세요. 여러 문자열을 함께 추가하면 매번 새 배열이 만들어집니다.

다음 예제를 살펴보세요.

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

매우 기본적인 것처럼 보이지만 표시되지 않는 것은 문자열이 추가 $message 될 때마다 완전히 새로운 문자열이 생성된다는 것입니다. 메모리를 할당하고 데이터를 복사한 다음 이전 데이터를 삭제합니다. 그것은 단지 몇 번 수행 할 때 큰 문제가 아니지만,이 같은 루프는 정말 문제를 노출 할 것이다.

StringBuilder

StringBuilder는 많은 작은 문자열에서 큰 문자열을 작성하는 데도 매우 인기가 있습니다. 사용자가 추가한 문자열만 수집하며 사용자가 값을 검색할 때만 모든 문자열을 연결하기 때문입니다.

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

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

다시 말하지만, 이것은 내가 .NET에 도달하고있는 것입니다. 나는 더 이상 자주 사용하지 않지만 거기에 있다는 것을 아는 것이 좋다.

중괄호를 사용하는 설명

문자열 내에서 접미사를 연결할 때 사용합니다. 변수에 깨끗한 단어 경계가 없는 경우가 있습니다.

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

그 하나에 대한 레디토르 u/real_parbold 감사합니다.

다음 방법을 사용해도 됩니다.

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

나는 개인적으로 이것을 위해 형식 문자열을 사용하지만, 이것은 당신이 야생에서 그것을 볼 백서를 아는 것이 좋다.

토큰 찾기 및 바꾸기

이러한 기능 대부분은 자체 솔루션을 마련할 필요가 없게 하지만, 많은 템플릿 파일에서 내부 문자열을 바꿔야 할 때도 있습니다.

텍스트가 많은 파일에서 템플릿을 끌어왔다고 가정해 보겠습니다.

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

대체할 토큰이 많을 수 있습니다. 요령은 쉽게 찾아서 바꿀 수 있는 매우 고유한 토큰을 사용하는 것입니다. 나는 그것을 구별하기 위해 양쪽 끝에서 특수 문자를 사용하는 경향이있다.

나는 최근에 이것에 접근하는 새로운 방법을 발견했다. 자주 사용하는 패턴이므로 이 부분은 여기에 남겨 놓기로 했습니다.

여러 토큰 바꾸기

토큰 목록을 바꾸고 싶을 때 일반적인 방법을 사용합니다. 해시 테이블 안에 배치한 다음 반복 실행하여 바꾸기 작업을 수행합니다.

$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
}

필요한 경우 이러한 토큰을 JSON 또는 CSV에서 로드할 수 있습니다.

ExecutionContext ExpandString

작은따옴표로 대체 문자열을 정의하고 나중에 변수를 확장하는 영리한 방법이 있습니다. 다음 예제를 살펴보세요.

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

현재 실행 컨텍스트에 대한 호출 .InvokeCommand.ExpandString 은 대체를 위해 현재 범위의 변수를 사용합니다. 여기서 중요한 점은 변수가 $message 존재하기 전에 아주 일찍 정의할 수 있다는 것입니다.

조금만 확장하면 다른 값으로 이 대체를 반복해서 수행할 수 있습니다.

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

이 작업을 하려면 텍스트 파일에서 대형 이메일 템플릿을 가져오면 됩니다. 나는이 제안에 대한 마크 크라우스에게 감사해야합니다.

무엇이든 당신을 위해 가장 잘 작동

저는 형식 문자열 접근 방식의 팬입니다. 문자열이 복잡하거나 여러 변수가 있을 때 사용합니다. 매우 짧은 아무것도에, 나는이 중 하나를 사용할 수 있습니다.

다른 내용을 알고 싶으신가요?

지금까지 많은 내용을 설명했습니다. 이제 새로운 내용을 배워 보시기 바랍니다.

문자열 보간을 가능하게 하는 메서드 및 기능에 대해 자세히 알아보려면 다음 목록에서 참조 설명서를 확인하세요.