Ok, quindi dopo guardando questo per un po ', ho deciso ci doveva essere un modo per fare questo con un uno di linea. Eccolo:
(gc "c:\myfile.txt") | % -Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)} -Process {if ($_ -eq $test[0] -or $_ -eq $test[-1]) { $_ -replace "-" } else { $_ }} | Set-Content "c:\myfile.txt"
Qui è una ripartizione di ciò che questo sta facendo:
In primo luogo, gli alias per chi ormai familiare. Ho solo li metto in perché il comando è abbastanza lungo così com'è, quindi questo aiuta a mantenere le cose gestibile:
gc
significa Get-Content
%
significa Foreach
$_
è per il valore di pipeline corrente (questo isn 't un alias, ma ho pensato che definirei da quando hai detto che eri nuovo)
Ok, ora qui è ciò che sta accadendo in questo:
(gc "c:\myfile.txt") |
-> Ottiene il contenuto di c:\myfile.txt
e lo manda giù la linea
%
-> Fa un ciclo foreach (passa attraverso ogni elemento in cantiere individualmente)
-Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)}
-> Questo è un blocco iniziale, esegue tutto qui prima che entri nella roba della pipeline.Sta caricando la prima e l'ultima riga di c:\myfile.txt
in un array in modo che possiamo controllare il primo e l'ultimo articolo
-Process {if ($_ -eq $test[0] -or $_ -eq $test[-1])
-> Questo esegue un controllo su ogni elemento nella pipeline, controllando se si tratta del primo o dell'ultimo elemento in il file
{ $_ -replace "-" } else { $_ }
-> se è il primo o l'ultimo, lo fa la sostituzione, se non lo è, semplicemente lascia da solo
| Set-Content "c:\myfile.txt"
-> Questo mette i nuovi valori all'interno del file.
prega di consultare i seguenti siti per ulteriori informazioni su ciascuno di questi elementi:
Get-Content uses
Get-Content definition
Foreach
The Pipeline
Begin and Process parte del foreach (questo sono di solito per funzione personalizzata, ma funzionano anche nel ciclo foreach)
If ... else dichiarazioni
Set-Content
Quindi stavo pensando a cosa fare se si voleva fare questo a molti file o si voleva farlo spesso. Ho deciso di fare una funzione che fa ciò che stai chiedendo. Ecco la funzione:
function Replace-FirstLast {
[CmdletBinding()]
param(
[Parameter(`
Position=0, `
Mandatory=$true)]
[String]$File,
[Parameter(`
Position=1, `
Mandatory=$true)]
[ValidateNotNull()]
[regex]$Regex,
[Parameter(`
position=2, `
Mandatory=$false)]
[string]$ReplaceWith=""
)
Begin {
$lines = Get-Content $File
} #end begin
Process {
foreach ($line in $lines) {
if ($line -eq $lines[0] ) {
$lines[0] = $line -replace $Regex,$ReplaceWith
} #end if
if ($line -eq $lines[-1]) {
$lines[-1] = $line -replace $Regex,$ReplaceWith
}
} #end foreach
}#End process
end {
$lines | Set-Content $File
}#end end
} #end function
Questo creerà un comando chiamato Replace-FirstLast
. Si sarebbe chiamato in questo modo:
Replace-FirstLast -File "C:\myfiles.txt" -Regex "-" -ReplaceWith "NewText"
Il -Replacewith
è facoltativo, se è vuoto sarà sufficiente rimuovere (valore di default di ""
). -Regex
sta cercando un'espressione regolare che corrisponda al tuo comando. Per informazioni sul posizionamento questo nel tuo profilo di controllo this article
Si prega di notare: Se il file è molto grande (diversi GB), questa non è la soluzione migliore. Ciò farebbe sì che l'intero file vada in memoria, il che potrebbe potenzialmente causare altri problemi.
buona risposta, ma attenzione che se i file diventano enormi sarebbe meglio usare 'get-content -First 1' e' ... -Last 1' nell'istruzione begin in modo da non mantenere un file xxGB in memoria durante l'elaborazione. –
Vero, ma poi siamo tornati al problema di non tornare indietro l'intero file, solo la prima e l'ultima riga. – Nick
no. Ho detto nella dichiarazione iniziale 'foreach -begin {..here ...}'. :) –