0

次の Unix シェル スクリプトがあります。これを Windows ファイルに変換したいと思い.batます (Windows 環境に適応させる代わりに Cygwin を使用できることはわかっていますが、Cygwin は私にとって選択肢ではありません)。

Windows PowerShell の読み物をオンラインで使用できることを知っています。しかし、この 1 回限りの要件のために、基本からオンラインで学習するのに何時間も費やしたくありません。怠け者だからと言って私を叩かないでください。これは、将来オンラインで検索する人のためのクイックガイドになることで、他の人にも役立つと確信しています.

スクリプトは次のとおりです。

#!/bin/bash
echo ""
cat $1 | grep -A4 "Device_name"; echo ""
cat $1 | grep -A45 "Device_Oops"; echo ""
cat $1 | grep -A150 "Processes:" | sed '/Radar/q'; echo ""
cat $1 | grep -E '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]' | grep -i -E 'error|restart' 

私が試したことに関する質問に答えるために、この Web サイトhttp://tldp.org/LDP/abs/html/dosbatch.htmlfindに相当する " " コマンドの実行に問題があります。grep

これが私のJoy.txtファイルです(次の2行):

Device_name router@home
testing only

次に、PowerShell プロンプトで次のコマンドを実行しました。

cat Joy.txt | find "Device_name"

上記のファイルの最初の行が表示されることを期待していました。しかし、代わりに、パラメーター形式が正しくないというエラーが発生します。誰か助けてくれませんか?

4

2 に答える 2

5

Windows のネイティブの同等物である(または) には、多かれ少なかれ直接的な同等物はgrep -A存在しません。ただし、PowerShell では、これをパラメーターと一緒に持っています。findstrfindgrepSelect-String-Context

あなたのスクリプトを正しく理解していれば、それは次のことを意味します。

  • 空行を書く
  • "Device_name" を含むすべての行を記述し、その後に 4 行のコンテキストを記述し、その後に空の行を記述します。
  • 「Device_Oops」を含むすべての行を記述し、その後に 45 行のコンテキストを記述し、その後に空の行を記述します
  • "Processes:" も含まれている場合、または "Processes:" を含む行に続く最初の 150 行以内にある場合は、"Radar" を含むすべての行を書き込みます。
  • 「エラー」または「再起動」のいずれかを含むコロンで区切られた 3 組の数字を含むすべての行を、大文字と小文字を区別せずに記述します。

したがって、多かれ少なかれ次のようになります。

$f = Get-Content $args[0]
function Emulate-Grep {
    begin { $first = $true }
    process {
      if (!$first) { '--' }
      $_.Line
      $_.Context.PostContext
      $first = false
    }
}

Write-Host
$f | Select-String -CaseSensitive -Context 0,4 'Device_name' | Emulate-Grep; Write-Host
$f | Select-String -CaseSensitive -Context 0,45 'Device_Oops' | Emulate-Grep; Write-Host
[string[]]($f | Select-String -CaseSensitive -Context 0,150 'Processes:' | Emulate-Grep) -split "`n" -cmatch 'Radar'; Write-Host
$f -match '\d{2}(:\d{2}){2}' -match 'error|restart'

(未テスト)

grepの出力動作をエミュレートしようとするため、これは少し醜いことに注意してください。

一致する行と次のものが必要な場合は、単純に小さな関数を記述します。

function Get-Matching([array]$InputObject, [string]$Pattern, [int]$Context = 0) {
    $n = $InputObject.Length - 1
    0..$n |
      where { $InputObject[$_] -cmatch $Pattern } |   
      foreach { $InputObject[$_..($_+$Context)] }
}

そして、それほど複雑ではないスクリプトでそれを使用します(空の行など、出力の選択肢のいくつかを再作成しようとしています):

$f = gc $args[0]
Write-Host
Get-Matching $f Device_name 4; Write-Host
Get-Matching $f Device_Oops 45; Write-Host
Get-Matching $f 'Processes:' 150 | ? { $_ -cmatch 'Radar' }; Write-Host
Get-Matching $f '\d{2}(:\d{2}){2}' | ? { $_ -match 'error|restart' }

Select-Stringまた、目的をまったく理解していなかったコマンドレットである を削除したことにも気付くでしょう(ただし、 grep/の厳密な一致を提供することを除きfindstrますが、通常は他の手段の方が柔軟であることがわかります)。

于 2013-10-17T07:40:45.167 に答える