2014年10月10日金曜日

◆CRをCRLFに変換する

以下のTipsの内容をメモしておく。

Normalizing Line Endings - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources

 

たまに、どこかから取ってきたファイルなどで改行コードがCRだけの場合があり、メモ帳で開くと残念な結果になる。

少し高機能なエディターとかであればCRだけでも旨く表示してくれるし、CRLFに変換して保存したりも出来る。

上記Tipsによると、PowerShellでも簡単に変換が可能だ。
特に、Replaceとか使わずとも「Get-Content」で読んでそのまま「Set-Content」で出力するだけで良いのだそうだ。

---

以下の説明が詳しい
http://www.atmarkit.co.jp/ait/articles/1605/16/news023.html

2014年10月8日水曜日

◆パラメータ名の一部省略の不思議

コマンドレットのパラメータは他のパラメータと区別可能ならば途中までの文字で指定が可能だ。

image

dir –p と入力してタブを押すと「Path」しか出てこないので「p」だけでも良さそうだが、なぜか以下のようなエラーとなる。

PS>dir -p c:\
Get-ChildItem : パラメーター名 'p' があいまいなため、パラメーターを処理できません。一致する名前の候補は次のとおりです:
-Path -LiteralPath。
発生場所 行:1 文字:4
+ dir <<<<  -p c:\
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem]、ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.GetChildItemCommand

なぜ「LiteralPath」も対象になるのだろう。

2014年10月6日月曜日

◆IF文での判定条件の書き方

今更ながら基本の基本を確認しておく。

IF文での判定条件は普通に考えると、

if($a –eq 1){hogehoge}

てな感じに書くのが一般的な気がする。
ただし、これは一般的な他の言語と同様な書き方で一見何の問題も無いように見えるが、PowerShellの場合はちょっと事情が異なる。

例えば以前PowerShell: ◆配列をフィルターするで書いたように、配列などではイコール演算子が感覚とはちょっと違った動作をする。

この間、PowerShell: ◆閾値以下の空き容量のHDドライブがあったら警告するで使った抽出判定も、

if(Get-PSDrive | ?{$_.USED –ne “”}){hogehoge}

ってな感じでは旨くいかない。(余計なものが幾つか残ってしまう)
image

では、どうすればよいのか。
昔からなんとなく使っている以下の書き方が実は正しい書き方なのではと最近思っている。

if($a){hogehoge}

こう書いた場合、どう判定されるかというと(経験的に)、その変数のデータ型の初期値であればFalse、初期値以外がTrueになる。

数値であれば、0がFalse、文字列であれば””がFalse、オブジェクトであればNullがFalseといった具合。
配列がちょっと厄介だが、要素が複数の場合はTrue、ひとつの場合はその変数の属性に応じて上記と同様に判定される。

この機能はおそらく、PowerShellが$aをbool型に自動変換しているのだろう。
即ち、

if([bool]$a){hogehoge}

と書くのと同じではないかと思う。

image

 

先に書いた、

if(Get-PSDrive | ?{$_.USED –ne “”}){hogehoge}

のパターンでは、USEDプロパティがスクリプトプロパティなので、ドライブによってUSEDのデータ型が違ってきている。

なので、演算子を直接使って判定しようとすると

image

てな感じになってしまう。

これはやはり普段から

if($a){hogehoge}

の書き方を使うのが良いのだろうと思う。

ちなみに、「-ne」の場合は「!」を使って(!$a)とする。

 

あくまでも、経験則で考えたものですが・・・・。

2014年10月1日水曜日

◆閾値以下の空き容量のHDドライブがあったら警告する

>if(Get-PSDrive | ?{$_.used} | %{$_.Free / ($_.used + $_.free)} | ?{$_ -lt 0.6}){"HD容量不足発生";Read-Host}

image

ここでは閾値として0.6(60%)を指定している。

後はこれをスタートアップで実行しても良いし、サーバーなどを巡回しても良いしって感じだろうか。

---

質問があったので補足

各ドライブの空き容量を表示するにはとりあえずこんな感じで

>Get-PSDrive | ?{$_.used} | select name , @{name="残容量(%)";expression={[int](($_.Free / ($_.used + $_.free))*100)}}

image

2014年9月26日金曜日

◆Foreach-Objectのパラメータへの疑問

今更の感じはするが、Foreach-Objectの動作。

PS>1..3 | ForEach-Object{"開始"}{"ループ"}{"終了"}
開始
ループ
ループ
ループ
終了

本来、ヘルプを見ると位置オペランドは(-Process)だけなので、なぜこれで動くのだろうとちょっと疑問に思う。

ちなみに、以下は良いが、

PS>1..3 | ForEach-Object{"開始"}{"ループ"}

当然、以下は上と同じ書式なので「ループ」が初期処理とみなされる。

PS>1..3 | ForEach-Object{"ループ"}{"終了"}

なので、

PS>1..3 | ForEach-Object{"ループ"}  -end{"終了"}

とする必要が有りそう。

2014年9月11日木曜日

◆Get-Helpの怪

なぜか以下のようなエラーが発生する。

PS>get-help  演算子
Get-Help : 型 [Microsoft.ActiveDirectory.Management.ADUser] が見つかりません。この型を含むアセンブリが読み
ことを確認してください。
発生場所 行:1 文字:9
+ get-help <<<<  演算子
    + CategoryInfo          : InvalidOperation: (Microsoft.Activ...nagement.ADUser:String) [Get-Help]、Ru
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.GetHelpCommand

普通は「演算子」という文字列が含まれるヘルプが一覧表示される。

image

さ~、なんとしたものか・・・。

自分だけがおかしいということは「Profile」・・・。

案の定、プロファイル無しで起動したらエラーは発生しなかった。

さぁ、ではプロファイルの何が悪いのか・・・。

なんだかんだ使わない物やテスト的に入っているものもありプロファイルは結構な量になっている。

と嘆いても仕方が無いので2分割方?で探していく・・・・・・・・・・・・・・・・・・・。

やっと見つけた、これだ!!

$env:path += ";D:\svndoc\PS\;.\"

ん~、スクリプトの入ったフォルダをPath環境変数に追加しているだけだ。

もしかして、このスクリプトの中もヘルプで探しに行ってしまうのか?

Version3で同じ環境にして試した見たが再現しなかった。

という事は「バグ」か。(><)

2014年8月26日火曜日

◆検索文字列をハイライト表示する

環境変数に目的のパスが含まれているか確認したいことは良くあるが、結構なが~いのが普通なので年寄が目視で確認するのはちと辛い。

メモ帳に貼り付けて検索すれば事足りるのだが、やっぱりここはPowerShellでやってみたい。

幸いファイル群から文字列を検索してハイライト表示するスクリプトが以下で公開されていた。
Wes' Puzzling Blog - Powershell script to find strings and highlight them in the output

(通常はこちらのほうが使いでがあると思われる。)

とりあえずこれをそのまま利用させていただいて単純な文字列からのパターン検索に変更した。
やっつけで変更したので中身はほとんど理解していない・・・。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034

function Write-HostAndHighlightPattern(
  
[string] $pattern = ""
  , [string] $inputtext = ""
  , [switch] $caseSensitive = $false
)
{

 
if ($pattern -eq $null -or $pattern -eq ""
) { 
   
Write-Error "Please provide a search pattern!" ; return
 }

 
$regexPattern = $pattern
  if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern"
 }
 
$regex = New-Object System.Text.RegularExpressions.Regex $regexPattern

  $index = 0
  while($index -lt $inputText.
Length)
  {
   
$match = $regex.Match($inputText, $index
)
   
if($match.Success -and $match.Length -gt 0
)
    {
     
Write-Host $inputText.
SubString(
       
$index, $match.Index - $index) -nonewline
      Write-Host $match.Value.ToString() -Foreground Red -nonewline
      $index = $match.Index + $match.
Length
    }
   
else
    {
     
Write-Host $inputText.SubString($index) -nonewline
      $index = $inputText.
Length
    }
  }
}


Write-HostAndHighlightPattern "system32" $env:path

結果

image