英文:
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 + "`r`n" + $fileContents
It appends an array to $newString + "`r`n"
and when PowerShell stringifies an array, it joins its element with spaces (by default; the rarely used $OFS
preference variable can change that); try "foo: " + 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论