web-dev-qa-db-ja.com

Set-Contentは、ファイルの最後に改行(改行、CRLF)を追加します

私の元の設定ファイル(web1.config)には余分な行はなく、メモ帳(すべての文字を表示)で表示すると次のようになります。

enter image description here

 <?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" />
  </system.web>
  <appSettings>
    <add key="myConnectionString" value="server=localhost;database=myDb;uid=myUser;password=myPass;" />
  </appSettings>
</configuration>

次に、スクリプトを適用して、データベース名を次のような別の名前に変更する必要があります。

 Move-Item "web1.config" "webtemp.config"
Get-Content "webtemp.config" | ForEach-Object {$_ -replace "database=myDb;", "database=newDb;"} |Set-Content "web1.config" -Force
Remove-Item "webtemp.config"
Write-Output('Settings Changed')

そのため、生成される新しいファイル(web1.config)は次のようになります。

enter image description here

ファイルの最後に余分な行が追加されていることに注意してください(これは完全に不要です)。次のような他のすべてのオプションを試しました。-out-file apiの使用-.net IO method System.IO .StreamWriter--nonewlineフラグを使用(10行すべてを単一行に変換)-異なるエンコードオプションを使用-\ r\nを\ rに置き換えてみました(セットコンテンツが常にcrlfを生成するため、動作しません)

PowerShell v5.1を使用しています。

16
OmGanesh

tl; dr PSv5 +;古いバージョンについては下を参照):

(Get-Content webtemp.config) -replace "database=myDb;","database=newDb;" -join "`n" |
  Set-Content -NoNewline -Force web1.config

注:UnixスタイルのLFのみの行末ではなく、WindowsスタイルのCRLF行末が必要な場合は、"`n""`r`n"に置き換えます(PowerShellと多くのユーティリティが両方を処理できます)。


PSv5 + では、Set-Content-NoNewline switch をサポートします。これはSet-Content各入力オブジェクトの後に改行(改行)を追加しない。同じことがAdd-ContentおよびOut-Fileコマンドレットにも当てはまります。

つまり、Set-Content -NoNewline直接連結allの文字列表現=その入力オブジェクト

> 'one', 'two' | Set-Content -NoNewline tmp.txt; Get-Content tmp.txt
onetwo

Set-Content -NoNewlineに渡すものが単一の文字列である既に改行が埋め込まれているの場合、そのまま使用して目的の結果を得ることができます。

> "one`ntwo" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
one
two?

Get-Content -Rawはファイルを読み取ることに注意してください全体として、現状のまま(文字デコードを除く)、および?twoの直後に現れるという事実ファイルの末尾に改行がないこと。

あなたの場合、入力行を処理しているので1行ずつGet-Content経由なし-Rawarrayの行(文字列)を出力するには、最初にseparatorとして改行でそれらを結合する必要があります-between行のみ-上部に示すように、結果をSet-Content -NoNewlineに渡します。以下に簡単な例を示します。

> ('one', 'two') -join "`n" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
one
two?

'one', 'two'は、行ごとの処理コマンドの代用となる2要素の文字列配列です。

エンコーディングノート:

Windows PowerShellでは、Set-Contentは、システムの従来のシングルバイトコードページに基づいて、デフォルトで「ANSI」エンコードファイルを生成します。
エンコードを明示的に制御するには、-Encodingパラメーターを使用します。


PSv4-では、.NET Frameworkを使用するソリューションが必要です。

> [System.IO.File]::WriteAllText('tmp.txt', ('one', 'two') -join "`n"); "$(Get-Content -Raw tmp.txt)?"
one
two?

[System.IO.File]::WriteAllText() は、エンコード引数がない場合、デフォルトでBOMなしUTF-8になります。
必要に応じて、必要な[System.Text.Encoding]エンコーディングインスタンスを3番目の引数として渡します。

18
mklement0

私はこれに気付かなかったので、簡単な検索を行って見つけました:

set-contentはデフォルトで改行を追加します

推奨される解決策は、コンテンツをバイトにエンコードしてから、-Encodingパラメーターを指定してSet-Contentを使用することです。

Set-Content test.txt ([byte[]][char[]] "test") -Encoding Byte

自分でテストしたので、これが機能することを確認できます。

2
SteloNLD