¿Cómo canalizar solo las líneas que se reemplazaron en powershell?

Tengo esto:

(gc "$env:a.txt") -replace 'aaa', 'bbb'

Quiero canalizarlo de alguna manera para que imprima las líneas que se cambiaron (después del cambio), y solo ellas (sin simplemente buscar 'bbb', por supuesto..). Cómo ?

Edit:

Olvidé mencionar que quiero cambiar el archivo en el proceso, lo que lo hace más difícil (pero quiero ver, como "retroalimentación de cordura", solo las líneas actualizadas):

(gc "a.txt") -replace 'aaa', 'bbb' | something-here-?? | sc a.txt

¿Tengo que hacer eso en dos pasos o hay una manera de canalizarlos todos?

preguntado el 12 de junio de 12 a las 18:06

4 Respuestas

Para lo que quiere, para mostrar lo que se está cambiando y reemplazar el contenido del archivo, puede hacer:

gc test.txt | %{ 
    if($_ -match "this") {
        $replaced = $_ -replace "this","that"
        write-host $replaced
        $replaced
    } else{
        $_
    }

} | sc test2.txt

Si solo desea ver la diferencia después de reemplazar, puede usar compare-object

Respondido el 13 de junio de 12 a las 06:06

Le falta una línea en eso: no copiará las líneas coincidentes en el archivo test2.txt. Si edita su código para tener "$reemplazado" solo en una línea después de la línea "write-host $replaced", creo que eso es lo que quiso decir. - levin magruder

@LevinMagruder - Oh, sí, eso es lo que quise decir. - manojlds

Primero puede hacer coincidir el texto que desea reemplazar, luego reemplazar línea por línea...

(gc a.txt) -match 'aaa' | % { $_ -replace 'aaa', 'bbb' }

También quiero señalar que su código y el mío, que se deriva del suyo, en realidad no modifican el archivo original.

Respondido el 12 de junio de 12 a las 18:06

Olvidé mencionar que quiero cambiar el archivo en el proceso, lo que lo hace más difícil (pero quiero ver, como "retroalimentación de cordura", solo las líneas actualizadas): (gc "a.txt") -replace 'aaa', 'bbb' | something-here-?? | sc a.txt. Edité mi pregunta en consecuencia ... - Alquitrán

No veo ninguna razón para no usar el método de Seth, pero en caso de que haya algo sutil, o si simplemente disfrutas escribiendo: hay una diferencia incorporada. Para obtener solo la versión modificada de las líneas que cambiaron:

  diff (gc myfile) ((gc myfile) -replace "x", "y")) |  % { if ($_.SideIndicator -eq '=>') { $_.InputObject } }

(puede obtener tanto el origen como el cambio eliminando la prueba de SideIndicator)

Respondido el 12 de junio de 12 a las 18:06

Olvidé mencionar que quiero cambiar el archivo en el proceso, lo que lo hace más difícil (pero quiero ver, como "retroalimentación de cordura", solo las líneas actualizadas): (gc "a.txt") -replace 'aaa', 'bbb' | something-here-?? | sc a.txt. Edité mi pregunta en consecuencia. En ese caso, supongo que la diferencia es una buena opción, si no encuentro una forma más eficiente (o tal vez lo haga en dos pasos): Alquitrán

En realidad, Compare-Object tiene el parámetro -PassThru, por lo que no es necesario canalizar las cosas para que funcione...: diff (gc myfile) ((gc myfile) -replace 'x','y') -PassThru - BartekB

Puede usar ForEach-Object para verificar cada valor reemplazado por el nuevo valor y escribirlo. Solo asegúrese de continuar pasando todo por la canalización:

(Get-Content "a.txt") -replace 'aaa', 'bbb' | 
    ForEach-Object { if( $_ -like '*bbb*' ) { Write-Host $_ } $_ } | 
    Set-Content a.txt

Mostrará cualquier línea que ya contenga bbb. Si realmente solo quieres ver el antes y el después:

Get-Content "a.txt" | 
    ForEach-Object {
         if( $_ -match 'aaa' ) 
         {
             $newLine = $_ -replace 'aaa','bbb'
             Write-Host "> $_"
             Write-Host "< $newLine"
             $newLine
         }
         else
         {
             $_
         }

    } |
    Set-Content a.txt

Respondido el 12 de junio de 12 a las 20:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.