6

「-」を見つけて削除するには、テキストファイルの最初の行と最後の行のみを検索する必要があります。どうすればいいですか?選択文字列を試しましたが、最初と最後の行を見つけて、そこから「-」のみを削除する方法がわかりません。

テキストファイルは次のようになります。

 % 01-A247M15 G70 
N0001 G30 G17 X-100 Y-100 Z0
N0002 G31 G90 X100 Y100 Z45
N0003 ; --PART NO.:  NC-HON.PHX01.COVER-SHOE.DET-1000.050 
N0004 ; --TOOL:  8.55 X .3937 
N0005 ;  
N0006  % 01-A247M15 G70 

このようなもの?

$1 = Get-Content C:\work\test\01.I

$1 | select-object -index 0, ($1.count-1)
4

8 に答える 8

6

さて、これをしばらく見てから、ワンライナーでこれを行う方法が必要だと思いました。ここにあります:

(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"

これが行っていることの内訳は次のとおりです。

まず、今ではおなじみのエイリアス。コマンドがそのままで十分な長さであるため、これらを挿入するだけです。これにより、管理しやすくなります。

  1. gc意味Get-Content
  2. %意味Foreach
  3. $_現在のパイプライン値用です(これはエイリアスではありませんが、新しいと言ったので定義すると思いました)

さて、これがこれで起こっていることです:

  1. (gc "c:\myfile.txt") | ->のコンテンツを取得し、c:\myfile.txtそれを送信します
  2. % -> foreachループを実行します(パイプライン内の各アイテムを個別に通過します)
  3. -Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)} ->これは開始ブロックであり、パイプラインに入る前にここですべてを実行します。c:\myfile.txtの最初と最後の行を配列にロードしているので、最初と最後の項目を確認できます
  4. -Process {if ( $_ -eq $test[0] -or $_ -eq $test[-1] ) ->これにより、パイプライン内の各アイテムのチェックが実行され、ファイル内の最初のアイテムか最後のアイテムかがチェックされます。
  5. { $_ -replace "-" } else { $_ } ->最初または最後の場合は置換を行い、そうでない場合はそのままにします
  6. | Set-Content "c:\myfile.txt" ->これにより、新しい値がファイルに戻されます。

これらの各アイテムの詳細については、次のサイトを参照してください。

Get-Contentは
Get-Content定義を使用します
ForeachForeach
のパイプラインの
開始と処理の部分(これは通常カスタム関数用ですが、foreachループでも機能します)
If...elseステートメント
Set-Content

それで、これを多くのファイルに対して実行したい場合、またはこれを頻繁に実行したい場合はどうなるかを考えていました。私はあなたが求めていることを実行する関数を作ることにしました。関数は次のとおりです。

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

これにより、。というコマンドが作成されReplace-FirstLastます。それはこのように呼ばれるでしょう:

Replace-FirstLast -File "C:\myfiles.txt" -Regex "-" -ReplaceWith "NewText"

はオプションです。-Replacewith空白の場合は削除されます(デフォルト値は"")。は-Regex、コマンドに一致する正規表現を探しています。これをプロファイルに配置する方法については、この記事を確認してください

注意: ファイルが非常に大きい場合(数GB)、これは最善の解決策ではありません。これにより、ファイル全体がメモリ内に存在し、他の問題が発生する可能性があります。

于 2013-01-18T17:45:22.993 に答える
6

試す:

$txt = get-content c:\myfile.txt
$txt[0] = $txt[0] -replace '-'
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-'
$txt | set-content c:\myfile.txt
于 2013-01-18T15:58:56.353 に答える
1

基本的に、テキスト ファイルは 1 つの巨大な配列として出力されるため、select-objectコマンドレットを使用してこれを行うことができます。get-content

したがって、このようなことができます

get-content "path_to_my_awesome_file" | select -first 1 -last 1

-Replaceその後ダッシュを削除するには、スイッチを使用してダッシュを見つけて削除します。System.String.Replace(...)これは、正規表現ステートメントに一致し、文字列の配列全体も置き換えることができるため、メソッドを使用するよりも優れています!

それは次のようになります。

# gc = Get-Content. The parens tell Powershell to do whatever's inside of it 
# then treat it like a variable.
(gc "path_to_my_awesome_file" | select -first 1 -last 1) -Replace '-',''
于 2013-01-18T17:00:25.083 に答える
1

ファイルが非常に大きい場合、最後の行を取得するためにファイル全体を読みたくない場合があります。gc -Tail は最後の行を非常に迅速に取得します。

function GetFirstAndLastLine($path){

    return  New-Object PSObject -Property @{        
        First = Get-Content $path -TotalCount 1
        Last = Get-Content $path -Tail 1
        }
}

GetFirstAndLastLine "u_ex150417.log"

これを 20 GB のログ ファイルで試したところ、すぐに返されました。ファイルの読み取りには数時間かかります。

すべての削除コンテンツを保持し、最後からのみ削除する場合は、ファイルを読み取る必要があります。-Tail を使用すると、そこにあるかどうかを簡単に確認できます。

お役に立てば幸いです。

于 2015-05-08T09:16:28.367 に答える
0

ニックの答えに続いて:ディレクトリツリー内のすべてのテキストファイルでこれを行う必要があり、これが現在使用しているものです:

Get-ChildItem -Path "c:\work\test" -Filter *.i | where { !$_.PSIsContainer } | % { 
$txt = Get-Content $_.FullName; 
$txt[0] = $txt[0] -replace '-'; 
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-';
$txt | Set-Content $_.FullName
}

そしてそれは今うまくいっているようです。

于 2013-01-21T16:20:08.777 に答える
0

上記に対するより明確な答え:

$Line_number_were_on = 0
$Awesome_file = Get-Content "path_to_ridiculously_excellent_file" | %{ 
    $Line = $_ 
    if ($Line_number_were_on -eq $Awesome_file.Length) 
         { $Line -Replace '-','' } 
    else 
         { $Line } ; 
    $Line_number_were_on++ 
} 

私はワンライナーが好きですが、機能よりも簡潔さを優先すると、読みやすさが損なわれる傾向があることがわかりました。あなたが行っていることが、他の人が読んだり維持したりするスクリプトの一部になる場合は、読みやすさを考慮する必要があります。

于 2013-01-18T20:47:20.773 に答える