Lưu ý: Điều sau áp dụng cho Windows PowerShell .
Xem phần tiếp theo về ấn bản PowerShell Core (v6 +) đa nền tảng .
Trên PSv5.1 trở lên , ở đâu >
và thực sự >>
là bí danh của Out-File
, bạn có thể đặt mã hóa mặc định cho >
/ >>
/ Out-File
thông qua $PSDefaultParameterValues
biến tùy chọn :
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
Trên PSv5.0 hoặc bên dưới , bạn không thể thay đổi mã hóa cho >
/>>
, nhưng, trên PSv3 hoặc cao hơn , các kỹ thuật nói trên làm việc cho các cuộc gọi rõ ràng đểOut-File
.
(Biến $PSDefaultParameterValues
tùy chọn đã được giới thiệu trong PSv3.0).
Trên PSv3.0 trở lên , nếu bạn muốn đặt mã hóa mặc định cho tất cả các lệnh ghép ngắn hỗ trợ
một -Encoding
tham số (trong PSv5.1 + bao gồm >
và >>
), hãy sử dụng:
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
Nếu bạn đặt lệnh này trong của bạn$PROFILE
, các lệnh ghép ngắn chẳng hạn như Out-File
vàSet-Content
sẽ sử dụng mã hóa UTF-8 theo mặc định, nhưng lưu ý rằng điều này làm cho nó trở thành cài đặt toàn cầu phiên sẽ ảnh hưởng đến tất cả các lệnh / tập lệnh không chỉ định rõ ràng một mã hóa.
Tương tự, hãy đảm bảo bao gồm các lệnh như vậy trong các tập lệnh hoặc mô-đun mà bạn muốn hoạt động theo cùng một cách , để chúng thực sự hoạt động giống nhau ngay cả khi được chạy bởi một người dùng khác hoặc một máy khác.
Lưu ý : ** PowerShell, kể từ v5.1, luôn tạo tệp UTF-8 _ với BOM (giả) _ ** , điều này thường chỉ xảy ra trong thế giới Windows - Các tiện ích dựa trên Unix không nhận dạng BOM này (xem phần dưới); xem bài đăng này để biết các giải pháp thay thế tạo tệp UTF-8 không có BOM.
Để biết tóm tắt về hành vi mã hóa ký tự mặc định hoàn toàn không nhất quán trên nhiều lệnh ghép ngắn chuẩn của Windows PowerShell , hãy xem phần dưới cùng.
Tự động $OutputEncoding
biến là không liên quan , và chỉ áp dụng cho cách PowerShell giao tiếp với chương trình bên ngoài (những gì mã hóa sử dụng PowerShell khi gửi chuỗi cho họ) - nó không có gì để làm với mã hóa mà các nhà khai thác chuyển hướng đầu ra và PowerShell cmdlets sử dụng để lưu vào tập tin.
Đọc tùy chọn: Quan điểm đa nền tảng: PowerShell Core :
PowerShell hiện là nền tảng đa nền tảng , thông qua phiên bản PowerShell Core , có mã hóa - hợp lý - được mặc định thành UTF-8 không có BOM , phù hợp với các nền tảng giống Unix.
Điều này có nghĩa là các tệp mã nguồn không có BOM được giả định là UTF-8 và sử dụng >
/ Out-File
/ Set-Content
mặc định là UTF-8 không có BOM ; Việc sử dụng utf8
-Encoding
đối số một cách rõ ràng cũng tạo ra UTF-8 không có BOM, nhưng bạn có thể chọn tạo các tệp có BOM giả với utf8bom
giá trị.
Nếu bạn tạo tập lệnh PowerShell bằng trình chỉnh sửa trên nền tảng giống Unix và ngày nay ngay cả trên Windows với trình chỉnh sửa đa nền tảng như Visual Studio Code và Sublime Text, *.ps1
tệp kết quả thường sẽ không có BOM giả UTF-8:
- Điều này hoạt động tốt trên PowerShell Core .
- Nó có thể bị hỏng trên Windows PowerShell , nếu tệp chứa các ký tự không phải ASCII; nếu bạn cần sử dụng các ký tự không phải ASCII trong tập lệnh của mình, hãy lưu chúng dưới dạng UTF-8 với BOM .
Nếu không có BOM, Windows PowerShell (sai) diễn giải tập lệnh của bạn được mã hóa theo kiểu mã "ANSI" kế thừa (được xác định bởi ngôn ngữ hệ thống cho các ứng dụng trước Unicode; ví dụ: Windows-1252 trên hệ thống tiếng Anh-Mỹ).
Ngược lại, các file mà làm có UTF-8 pseudo-BOM thể được vấn đề trên Unix-như nền tảng, vì chúng gây ra các tiện ích Unix như cat
, sed
và awk
- và thậm chí một số biên tập viên như gedit
- để vượt qua pseudo-HĐQT thông qua , tức là, để coi nó như là dữ liệu .
- Điều này có thể không phải lúc nào cũng là một vấn đề, nhưng chắc chắn có thể xảy ra, chẳng hạn như khi bạn cố gắng đọc một tệp thành một chuỗi
bash
với, chẳng hạn, text=$(cat file)
hoặc text=$(<file)
- biến kết quả sẽ chứa BOM giả dưới dạng 3 byte đầu tiên.
Hành vi mã hóa mặc định không nhất quán trong Windows PowerShell :
Rất tiếc, mã hóa ký tự mặc định được sử dụng trong Windows PowerShell hoàn toàn không nhất quán; phiên bản PowerShell Core đa nền tảng , như đã thảo luận trong phần trước, đã kết thúc tốt đẹp vấn đề này.
Ghi chú:
Phần sau không bao gồm tất cả các lệnh ghép ngắn chuẩn.
Các tên lệnh ghép ngắn trên Google để tìm các chủ đề trợ giúp của chúng hiện hiển thị cho bạn phiên bản PowerShell Core của các chủ đề theo mặc định; sử dụng danh sách phiên bản thả xuống phía trên danh sách chủ đề ở bên trái để chuyển sang phiên bản Windows PowerShell .
Kể từ khi viết bài này, tài liệu thường tuyên bố không chính xác rằng ASCII là mã hóa mặc định trong Windows PowerShell - hãy xem sự cố tài liệu GitHub này .
Cmdlets viết :
Out-File
và >
/ >>
tạo "Unicode" - UTF-16LE - tệp theo mặc định - trong đó mỗi ký tự trong phạm vi ASCII (quá) được biểu thị bằng 2 byte - điều này đáng chú ý khác với Set-Content
/ Add-Content
(xem điểm tiếp theo); New-ModuleManifest
và Export-CliXml
cũng tạo tệp UTF-16LE.
Set-Content
(và Add-Content
nếu tệp chưa tồn tại / trống) sử dụng mã hóa ANSI (mã hóa được chỉ định bởi trang mã kế thừa ANSI của ngôn ngữ hệ thống đang hoạt động, mà PowerShell gọi Default
).
Export-Csv
thực sự tạo ra các tệp ASCII, như được ghi lại, nhưng hãy xem các ghi chú -Append
bên dưới.
Export-PSSession
tạo tệp UTF-8 với BOM theo mặc định.
New-Item -Type File -Value
hiện đang tạo BOM-less (!) UTF-8.
Các Send-MailMessage
chủ đề trợ giúp cũng tuyên bố rằng mã hóa ASCII là mặc định - Tôi đã không đích thân xác nhận rằng tuyên bố.
Start-Transcript
luôn tạo tệp UTF-8 với BOM, nhưng hãy xem ghi chú -Append
bên dưới.
Lệnh Re nối vào một tệp hiện có:
>>
/ Out-File -Append
Làm không cố gắng để phù hợp với mã hóa của một tập tin nội dung hiện có . Có nghĩa là, họ áp dụng mã hóa mặc định của mình một cách mù quáng, trừ khi được hướng dẫn khác với -Encoding
, không phải là một tùy chọn với >>
(ngoại trừ gián tiếp trong PSv5.1 +, thông qua $PSDefaultParameterValues
, như được hiển thị ở trên). Tóm lại: bạn phải biết mã hóa nội dung của tệp hiện có và nối thêm bằng cách sử dụng cùng mã hóa đó.
Add-Content
là ngoại lệ đáng khen ngợi: trong trường hợp không có -Encoding
đối số rõ ràng , nó sẽ phát hiện mã hóa hiện có và tự động áp dụng nó cho nội dung mới. Cảm ơn, js2010 . Lưu ý rằng trong Windows PowerShell, điều này có nghĩa là mã hóa ANSI được áp dụng nếu nội dung hiện có không có BOM, trong khi đó là UTF-8 trong PowerShell Core.
Sự mâu thuẫn này giữa Out-File -Append
/ >>
và Add-Content
, cũng ảnh hưởng đến PowerShell Core , được thảo luận trong vấn đề GitHub này .
Export-Csv -Append
khớp một phần với mã hóa hiện có: nó nối UTF-8 một cách mù quáng nếu mã hóa của tệp hiện có là bất kỳ ASCII / UTF-8 / ANSI nào, nhưng khớp chính xác UTF-16LE và UTF-16BE.
Nói cách khác: trong trường hợp không có BOM, Export-Csv -Append
giả sử UTF-8 là, trong khi Add-Content
giả định ANSI.
Start-Transcript -Append
khớp một phần với mã hóa hiện có: Nó khớp chính xác các mã hóa với BOM , nhưng mặc định là mã hóa ASCII có khả năng mất dữ liệu nếu không có.
Cmdlets đọc (nghĩa là mã hóa được sử dụng trong trường hợp không có BOM ):
Get-Content
và Import-PowerShellDataFile
mặc định là ANSI ( Default
), phù hợp với Set-Content
.
ANSI cũng là thứ mà công cụ PowerShell tự mặc định khi nó đọc mã nguồn từ các tệp.
Ngược lại, Import-Csv
, Import-CliXml
và Select-String
giả định UTF-8 trong sự vắng mặt của một BOM.
>
/>>
trở thành bí danh hiệu quảOut-File
trong 5.1 không?