문자열에서 변수를 사용하는 방법에는 여러 가지가 있습니다. 변수의 값을 포함하도록 문자열의 서식을 지정하려는 모든 경우를 "변수 대체"라고 부릅니다. 이것은 내가 자주 초보 스크립터에게 설명하게 되는 것이다.
비고
이 문서의 원래 버전@KevinMarquette작성한 블로그에 나타났습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com자신의 블로그를 확인하세요.
연결하기
메서드의 첫 번째 클래스를 연결이라고 할 수 있습니다. 기본적으로 여러 문자열을 가져와 함께 조인합니다. 연결을 사용하여 형식이 지정된 문자열을 빌드한 오랜 기록이 있습니다.
$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"
당신은 CreationTime의 $directory을(를) 얻을 것으로 예상되지만, 대신 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-Path 및 Test-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)
}
이 아이디어를 계속 진행하려면 이 작업을 수행하려면 텍스트 파일에서 큰 전자 메일 템플릿을 가져올 수 있습니다. 나는이 제안에 대한 마크 크라우스 에게 감사해야합니다.
당신에게 가장 잘 맞는 것을 선택하세요
저는 형식 문자열 접근 방식의 팬입니다. 나는 확실히 더 복잡한 문자열이나 여러 변수가있는 경우이 작업을 수행합니다. 매우 짧은 것에는, 이 중 아무거나 사용할 수 있습니다.
다른 것?
나는 이 작업에서 많은 진전을 이루었다. 제 희망은 새로운 것을 배우는 것입니다.
링크
문자열 보간을 가능하게 하는 메서드 및 기능에 대해 자세히 알아보려면 참조 설명서에 대한 다음 목록을 참조하세요.
- 접합은 덧셈 연산자를 사용합니다.
- 변수 및 명령 대체는 따옴표 규칙을 따릅니다.
- 포맷 연산자를 사용하는 서식 지정
- 문자열 연결에는 조인 연산자 및
Join-Path를 참조하는 것을 사용하지만, 또한Join-String에 대해 읽어볼 수도 있습니다. - 배열에 대한 정보는 기록되어 있습니다.
- StringBuilder는 자체 설명서가 있는 .NET 클래스입니다.
- 문자열의 중괄호는 따옴표 규칙에서도 다룹니다.
- 토큰 교체는 바꾸기 연산자를 사용합니다.
- 이
$ExecutionContext.InvokeCommand.ExpandString()메서드에는 .NET API 참조 설명서가 있습니다.
PowerShell