使用PowerShell,如何在文本文件的第一行插入一个标题行?

huangapple go评论72阅读模式
英文:

With PowerShell, how do I insert a header row to the first line of a text file?

问题

我能够将文件的内容以$newstring作为前缀添加。然而,新的“修改过的”文件只有两行。这段代码在某处去除了原始文件($filename)中的所有回车符和换行符。不确定哪里出错了。

英文:

I was able to prepend the file with the content of $newstring.

$sourceDirectory = "C:\SFTP_Root\kcmosdftp\"
$keyword = "User_ID|User_Alt_ID"
$newString = "User_ID|User_Alt_ID|Home_Room_Teacher|User_Group_ID|User_First_Name|User_Middle_Name|User_Last_Name|User_Library|User_Profile|User_Category1|User_Category2|User_Category3|User_Category4|User_Category5|User_Category10|User_Priv_Granted|User_Priv_Expires|Password|Street|City_State|zip|Email|PHONE|User_Birth_Date"

# Set the file name to search for
$fileName = "INBOUND-Student_New_File_Format.txt"

# Get the latest file in the source directory
$latestFile = Get-ChildItem -Path $sourceDirectory | Sort-Object LastWriteTime -Descending | Select-Object -First 1

# Check if the latest file contains the specified keyword
$containsKeyword = (Get-Content $latestFile.FullName) | Select-Object -first 1

if ($containsKeyword -notmatch $keyword) {
    # Read the contents of the latest file
    $fileContents = Get-Content $latestFile.FullName

    # Insert the new string at the beginning of the contents
    $fileContents = $newString + "`r`n" + $fileContents

    # Determine the new file path
    $newFilePath = Join-Path -Path $sourceDirectory -ChildPath "Modified_$($latestFile.Name)"

    # Write the modified contents to the new file
    $fileContents | Set-Content $newFilePath
    Write-Host "Added the string to the first row of $($latestFile.Name). New file saved as $($newFilePath)."
}
else {
    Write-Host "The latest file already contains the keyword."
}

Though, the new "modified" file has only two rows. Somewhere this code stripped out all of the carriage returns and new lines that were in original file ($filename).

Not sure where I went wrong here.

答案1

得分: 1

将以下内容更改为(注意使用 -Raw):

if ($containsKeyword -notmatch $keyword) {
    # 读取最新文件的内容
    $fileContents = Get-Content $latestFile.FullName -Raw
}

这样 $fileContents 就会成为一个__单个多行字符串__,而不是一个__字符串数组__。

当你尝试将左操作数的字符串与一个数组连接时,该数组会被强制转换为字符串,然后由 $OFS(默认为一个空格 )连接。

示例:

$myArr = 'foo', 'bar', 'baz'
$newString = 'hello world'
$newString + "`r`n" + $myArr

输出:

hello world
foo bar baz

而不是你期望的:

hello world
foo
bar
baz
英文:

Change the following:

if ($containsKeyword -notmatch $keyword) {
    # Read the contents of the latest file
    $fileContents = Get-Content $latestFile.FullName

To (notice the use of -Raw):

if ($containsKeyword -notmatch $keyword) {
    # Read the contents of the latest file
    $fileContents = Get-Content $latestFile.FullName -Raw

This is so $fileContents becomes a single multi-line string instead of an array of strings.

When you try to concatenate a string in the left-hand side of the operation with an array, said array gets coerced into string thus joined by $OFS (a space by default).

Example:

$myArr = 'foo', 'bar', 'baz'
$newString = 'hello world'
$newString + "`r`n" + $myArr

Outputs:

hello world
foo bar baz

Instead of what you expected:

hello world
foo
bar
baz

答案2

得分: 1

Get-Content 默认返回文本文件的逐行内容,逐行返回成为数组。

因此,以下内容按预期工作:

> $fileContents = $newString + "`r`n" + $fileContents

它将一个数组附加到 $newString + "`r`n" 上,当 PowerShell 字符串化 一个数组时,它会使用空格连接其元素(默认情况下;很少使用的 $OFS 优先变量可以更改这个);尝试 "foo: " + 1, 2, 3,它会直接返回 foo: 1 2 3

在你的情况下,最简单且性能更好的解决方案是使用 Get-Content-Raw 开关将文件读取为单个、多行字符串,这样你的字符串连接将按预期工作。

$fileContents = Get-Content -Raw $latestFile.FullName

然而,鉴于 Set-Content 的工作方式,你甚至不需要字符串连接,可以将两个字符串 - 新的标题行和包含现有文件内容的多行字符串 - 分开传递:

$newString, $fileContents | Set-Content $newFilePath
英文:

<!-- language-all: sh -->

Get-Content by default returns the individual lines of a text file, one by one, which, when captured, becomes an array.

Therefore, the following does not work as intended:

> $fileContents = $newString + &quot;`r`n&quot; + $fileContents

It appends an array to $newString + &quot;`r`n&quot; and when PowerShell stringifies an array, it joins its element with spaces (by default; the rarely used $OFS preference variable can change that); try &quot;foo: &quot; + 1, 2, 3, which yields verbatim foo: 1 2 3.

The simplest - and better-performing - solution in your case is to use Get-Content's -Raw switch to read your file as a single, multiline string, in which case your string concatenation would work as intended.

$fileContents = Get-Content -Raw $latestFile.FullName

However, given how Set-Content works, you don't even need the string concatenation and can pass the two strings - the new header line and the multiline string with the existing file content -
separately:

$newString, $fileContents | Set-Content $newFilePath

huangapple
  • 本文由 发表于 2023年6月2日 02:50:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定