PowerShell -Part 4
■ このスレッドは過去ログ倉庫に格納されています
インクリメントのループはこう書いたほうがスッキリする foreach ($i in 0..9) { >>797 こういうパイプがネストしてるのに違和感あるんだけど 多少効率悪くてもパイプ1本にできないかな for ($i=1; $i -le 2; $i++){ Switch($i) { 1 {(1..10) | %{"ikkaime_"+$_}} 2 {(1..10) | %{"nikkaime_"+$_}} } } パイプは繋げてナンボ UNIX文化からの流れで、シンプルなコマンド群からの組み合わせの可能性は無限大 長いパイプラインが違和感? いやロシアからウクライナを経由してドイツまで延びてもいい…!ゴルビーもそう言ってるよ 0..9 | % { "ikkaime_$_"; "nikaime_$_" } | sort function hoge($fuga) { 0..9 | ForEach-Object {Write-Output "$fuga$_"} } hoge 'ikkaime' hoge 'nikaime' >>800 "ikkaime_","nikaime_" | %{$hoge=$_;0..9} | %{$hoge+$_} >>802 長いパイプじゃなく、パイプライン処理の名にそぐわない、 行って帰ってくるようなネストされてるのが気持ち悪い >>803 >>805 そうそうこういうのがいいね ゴルビーのパイプライン大作戦にだって行って帰ってくるようなパイプは無いだろ 変数を事前に全部固めた書いたほうがわかりやすいと思うのですが、 ループ前に定義した変数の値に、ループ時の変数を入れ込む方法がわかりません $mynameis変数をループ中(コメントの位置)に持ってくると、問題ないんですが、 なんとか#変数ってしてあるところにもってきたいんです 定義したときには空で、あとから追加で変数に値をいれることってできないんでしょうか? ソース #変数 $watashi = "私は" $fname = "佐藤" $mynameis = "$watashi$fname$lname" foreach ($lname in "一郎","二郎","三郎"){ #$mynameis = "$watashi$fname$lname" #名を名乗る Write-Output $mynameis } $mynameis = { "$watashi$fname$lname" } $watashi = "私は" $fname = "佐藤" foreach ($lname in "一郎","二郎","三郎"){ #名を名乗る Write-Output (mynameis) } >Write-Output (mynameis) Write-Output (&$mynameis) こうかも、PowerShell難しすぎ foreachはスコープ作らなかったと思うけど 何が問題なの? ごめんようやく理解した 最初にNew-Variableなり空文字で宣言するだけじゃ納得いかんのかな 変数が自動で書き変わるのは正直気持ち悪い $watashi = "私は" $fname = "佐藤" $mynameis = "$watashi$fname{0}" foreach ($lname in "一郎","二郎","三郎"){ Write-Output ($mynameis -f $lname) } モダンな言語を使って書くレガシープログラミングだね 先頭宣言教から改宗してもらうのが一番丸く収まるとか言ったらダメなんだろうな できないことはないってだけで、やめたほうがいい 他の人がコードを読む時にとても困惑させるし 半年後に自分が読んでも理解に苦しむかもしれない 意外とPerl的なスパゲッティの罠がある言語なのね >>810 みたいにスクリプトブロックで評価順序制御するのは別におかしくないと思うけど 変数宣言を冒頭に集めるという、昔の言語ではルールだったけどデメリットの方が多いとして廃れた風習 その実現にスクリプトブロックを多用するのは可読性を落とすからやめとけという話じゃないかな 古典言語には存在しなかった文字列補間は、宣言したスコープで即時解決されるものだから冒頭部でリテラルを宣言する風習と相性が悪い 記法が似ていて混同したのだろうけど、質問者が暗に期待していたであろうフォーマットパターン文字列としてはPowershellでは -f 演算子が用意されているのでそれを使えばいい この話をPowershellの罠とされてしまうのはさすがにかわいそう $watashi = "私は" $fname = "佐藤" $lname = "一郎","二郎","三郎" $lname.ForEach{Write-Output "$watashi$fname$_"} "私は"と"佐藤"を分ける意味がない 気持ちは分からなくもないけど 1. webからテキストをDLしてカレントディレクトリに Shift-JIS で保存したい。どう書けばいいですか? https://example.com/test.txt 文字コード:UTF-8 コマンドプロンプトから以下でDL出来るのまでは調べて分かったんだけど文字コードを変えて保存するのが分かりません powershell -Command "Invoke-WebRequest https://example.com/test.txt -OutFile test.txt" コマンドプロンプトにコピペかバッチから使いたいのでワンライナーで出来ると嬉しいです 2. 1に似た処理でweb上のUTF-8のtest.txtをカレントディレクトリのShift-JISのabc.txtに追記したい こちらもコマンドプロンプトから powershell -Command "〜 みたいに出来ればワンライナーで >>824 Invoke-WebRequestのOutFileオプションじゃなくて、EncodingオプションのあるOut-Fileコマンドレットの方を使ったら? (cmdじゃなくてpowershellから実行すれば、powershell -Command ""の部分はいらないよ) Invoke-WebRequest https://example.com/test.txt | Out-File -Encoding default test.txt 追記するなら、Appendオプション Invoke-WebRequest https://example.com/test.txt | Out-File -Encoding default abc.txt -Append >>825 レスありがとうございます。ですが出来ませんでした Fileは作られるのですが内容が以下のようになります StatusCode : 200 StatusDescription : OK Content : ここに中身が複数行 尻切れ RawContent : HTTP/1.1 200 OK Connection: keep-alive x-robots-tag: noarchive, nofollow, noindex なんか色々 Forms : {} Headers : 諸々 Images : {} InputFields : {} Links : {} ParsedHtml : mshtml.HTMLDocumentClass RawContentLength : 中身、Content +尻切れ部分 で保存するにはどう書けばいいですか? Win10.0.18363.1256 PSVersion 5.1.18362.1171 (Invoke-WebRequest https://example.com/test.txt ).Content | Out-File -Encoding default test.txt >>827 出来ました!ありがとうございます! なんかオリジナル(UTF-8 LF)に比べ変換した(Shift-JIS CRLF)では末尾に改行コード1つ余分に追加されてしまいますが。。 バッチで読み直して再保存すれば行けそうです やりたいことが可能になりました。感謝! >末尾に改行コード1つ余分に追加されてしまいます こういうの気持ち悪い! 誰か助けてあげて! ググって出てくるやつだとPowershellのVer5以上なら (Invoke-WebRequest https://example.com/test.txt ).Content | Out-File -Encoding default test.txt -NoNewline >>829 ありがとうございます。私もモヤモヤしてたので調べて報告するつもりでした >>830 ありがとうございます -NoNewline で末尾改行追加されませんがLFのままになってしまうようです たぶんLFをCRLFにreplaceしてからOut-File -NoNewline で行けそうかも、というところまで来ていたのですが、、 置換のコマンドレットが分からず苦戦しています >>831 .NETのString.Replace() powershell -Command "%{((Invoke-WebRequest https://example.com/test.txt ).Content) -join '`r`n'}|Out-File abc.txt -Encoding default -Append -NoNewline" powershell -Command "%{((Invoke-WebRequest https://example.com/test.txt ).Content) -replace '`n,`r`n'}|Out-File abc.txt -Encoding default -Append -NoNewline" リファレンスとにらめっこし何百回と色々試してこれに行き着いてこれなら行けそうと思ったのですがLFのまま。。 Get-ContentとかSet-Contentとかも試してみたのですが基礎的な書き方も知らず当てずっぽうではダメなようです 基礎的な事から覚えないとちょっと自分には無理かもです^^; SurfacePro8の、一応待たれてはいるがあまり期待されてない感は異常 >>833-834 "`n", "`r`n" じゃねーの? >>836 ヒントありがとうございます 最終的に以下で出来ました ren jane2ch.brd jane2ch.brd.bak &© jane2ch.brd.bak jane2ch.brd &&powershell -Command "(Invoke-WebRequest https://example.com/bbsmenu.brd ).Content -replace \"`n\",\"`r`n\"|Out-File jane2ch.brd -Encoding default -Append -NoNewline" アドバイス下さった方皆ありがとう Invoke-WebRequestはaliasで短くできるよ (Get-Alias -Definition Invoke-WebRequest).Name curl iwr wget Out-Fileはaliasが無い 関数とクラスメソッドでreturnまわりの振舞い全然違うのかよ ほんまクソやな 自分が言語を知らないだけなのに言語を叩くやつは技術力があれだって書込みをLinuxスレで見た 謙虚になって勉強もせずに自分の知ってる言語に固執するらしい 関数のreturnは単に関数を抜けるだけ 出力はストリームを使う クラスのメソッドはreturn文でのみ値を返す 多くの言語でよくみられるやつ Write-Outputしても無視される 変数のスコープも違うよねー function f() { echo $a } $a = "test" f 関数はこれが気持ち悪すぎてメソッドしか使わなくなった 質問です。 .NETのKeyedCollectionクラスを使用したいのですが、 パイプラインに関するエラーメッセージが出てうまくいきません。 解決方法を教えていただけませんか。 環境はWindowsPowerShell 5.1をVSCode上で実行しています。 ソースコードとエラーメッセージは下記のとおりです。 ◆ソースコード class Record { [string] $Key [double] $Data } class MyCollection : System.Collections.ObjectModel.KeyedCollection[string, Record] { [string] GetKeyForItem([Record] $item) { return $item.Key } } $r = [Record]@{ Key = "pi"; Data = 3.14 } $c = [MyCollection]::new() $c.Add($r) $c["pi"].Data # 3.14と表示されてほしい ◆エラーメッセージ: パイプラインの作成中にエラーが発生しました。 + CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : RuntimeException 以上、よろしくおねがいします。 クラスごとにファイル分けてドットソースで読み込んで >>847 うちでも再現したわ Win10 1909 一応定義をC#で書いたら動いたから載せておく Add-Type @" public class Record { public string Key; public double Data; } public class MyCollection : System.Collections.ObjectModel.KeyedCollection<string, Record> { protected override string GetKeyForItem(Record item) { return item.Key; } } "@ $r = [Record]@{ Key = "pi"; Data = 3.14 } $c = [MyCollection]::new() $c.Add($r) $c["pi"].Data # 3.14と表示されてほしい ごめん >>846 宛ね >>847 まじですか でもPSの運用的にクラス定義で複数ファイルに分けるとかありえないわ コンソールからだと丸ごとコピペじゃなくて定義を1個ずつコピペするとエラーにならないし なんなのかね PowerShellのclassってどの段階で解釈されるんだろう 実行文が入っていない 単にコンパイルされる文、型の宣言・定義しか入っていない。 インスタンスを作ったりする、実メモリの割り付けをされる文がない >>851 クラス定義のps1ファイルの中身はそうすべき、ということでしょうか? >>849 確かにコンソールで全て定義すると動きますね。 クラス周りの動きが難しいです。。。 >>847 ありがとうございます。 下記のように書き直したところうまく動きました。 ◆Record.ps1 class Record { [string] $Key [double] $Data } ◆MyCollection.ps1 . .\Record.ps1 # ←これは無くても動く…?? class MyCollection : System.Collections.ObjectModel.KeyedCollection[string, Record] { [string] GetKeyForItem([Record] $item) { return $item.Key } } ◆Test.ps1 . .\Record.ps1 . .\MyCollection.ps1 $r = [Record]@{ Key = "pi"; Data = 3.14 } $c = [MyCollection]::new() $c.Add($r) $c["pi"].Data # 3.14と表示されてほしい ファイルA の中で、ファイルB を読み込むと、 依存ファイルであるファイルBが、先に実行される事が確定するのだろう 一方、同じファイルに、複数のクラスを書くと、依存関係が分からないのだろう すいません、Powershellって、変数が空だった場合の デフォルト値を設定する方法ってありますか? bashでいうところの、 ${hoge:-fuga} って方法です。 ねーよ VBSで言うIsEmpty相当すらない せいぜい$nullかどうか調べてちっ仕方ねーなってやるしかない ($nullでなく)空って状態はないと思うから、しいてやるならGet-Variableで変数が存在するか調べるくらいかね >>854 PowerShell 7の??演算子はいかがでしょうか >>854 変数が空の定義次第だけど$nullでよくてPowerShell 7以降なら$hoge ?? 'fuga' でいける 空の定義に空文字を含むとかPowerShell 6以下とかなら素直に if([string]::IsNullOrEmpty($hoge)){ 'fuga' } else { $hoge } とやればいい >>856 変数の存在確認ならTest-Path Variable:hogeの方が楽だと思う >>854 >${hoge:-fuga サザエさんかよw ほげふがの語源ってサザエさんだったの!? マジで! 来週もまた観てくださいね $hong -or $fouf 逆にメタ変数でhoge、fugaってそこまでマイナーか? >>867 そうか、それはすまなかった。 早とちりでございました。 お詫び申し上げます。 >>868 詫びろとは言ってない >>867 誰かがマイナーと言ったとは言ってない >>865 今週観たとは言ってない >>861 ご指摘にはあたらない ※すべてのネットワークアダプタを無効にして、 Get-NetConnectionProfileは必ずエラーになる状態で実行しています。 $result=Get-NetConnectionProfile -InterfaceAlias Wi-Fi 2>$null $? False $result=(Get-NetConnectionProfile -InterfaceAlias Wi-Fi 2>$null) $? True この場合、マル括弧がどんな働きをして 結果が変わってしまうのか教えてください。 ちなみにこうしても $result=Get-NetConnectionProfile -InterfaceAlias Wi-Fi エラーメッセージ $? False $result=(Get-NetConnectionProfile -InterfaceAlias Wi-Fi) エラーメッセージ $? True という状態でした。 >>872-873 まあバグ(MS的には仕様とも言う)みたいなもんやね Until PowerShell 7, containing a statement within parentheses (...), subexpression syntax $(...) or array expression @(...) always reset $? to True , so that (Write-Error) shows $? as True. This has been changed in PowerShell 7, so that $? will always reflect the actual success of the last command run in these expressions. https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.1#short-description なのでPowerShellを7にすれば解決するかと 5.1はメンテしないってことか? OSにデフォで入ってるバージョンなんだから直せよ いきなり直したらユーザースクリプトのバグが顕在化したりするだろ どうでもいいようなスクリプトなら7に上げろよ どうでもいいスクリプトで問題回避できるなら7に上げなくてもいいんじゃね。 >>874 ありがとうございます。 あげるのも怖いので別の方法にします。 >>878 あげる?のではなくて別物なので併用できるけど。 5.1 → powershell.exe 7.x → pwsh.exe 以下の表記の意味を教えてください。 void Queue[TResponse](Google.Apis.Requests.IClientServiceRequest request, Google.Apis.Requests.BatchRequest+OnResponse`1[TResponse] callback) メソッドに角カッコ?や、型指定に+や`1[TResponse]の意味がわかりませんでした。 $batch = New-Object Google.Apis.Requests.BatchRequst($service) $batch.Queue で表示される内容です。 クラスのメンバーにクラスがある時は+になるんじゃなかったか System.Environment+SpecialFolder みたいな [TResponse]はジェネリックの型引数 `1は型引数を1つ取るって意味 >>882 ありがとうございます。ジェネリックというのは知らなかったので調べてみます。 あと、その、Queue[TResponse]、というメソッドに型が付いている?のもジェネリック関連でしょうか。 >>884 え?Pythonから.NET Framework扱えるようになるの? 【D:\】の全てのフォルダやファイルに対して、作成日時や最終アクセス日時などを設定したいのですが、 PS D:\> Get-ChildItem -Path "D:\" | Where-Object { $_ -is [System.IO.FileInfo] } | ForEach-Object { Set-ItemProperty $_.FullName -Name CreationTime -Value "2021/01/01 00:00:00" } ではエラーが出ます。 何がいけないのでしょうか? 例えば特定の一つのファイルやフォルダなら上手く行くとか パイプを分解してどこでエラーになってるのかを突き止めるとか 丸投げするにしてもエラーメッセージ位は出してあげると答える人も喜ぶと思いますよ 1.D:\が存在していない 2.D:\へのアクセス権がない 3.D:\にあるファイルに読み取り専用属性が設定されてるものが混ざってる どれかな? Where-Object { $_ -is [System.IO.FileInfo] }抜き、ファイルに限定しないで実行したときは フォルダへのアクセス時にエクスプローラー開いてると ”別のプロセスで使用されているためアクセスできません”となった(たとえ操作対象のフォルダを開いていなくても) 変更された日時を確認するためにエクスプローラー開いたまま実行してたりする? # set the target folder path $targetFolder = 'I:\'; # get all files including files in sub folders $itemList = Get-ChildItem $targetFolder -Recurse; foreach($item in $itemList){ $item.CreationTime = '2020/12/21 00:00:00' } なスクリプトで実行したらエラーなく出来ました。 お騒がせしてすみませんでした。 >>893 >>890 私の環境で実行したら何のエラーもなく、CreationTimeが2021/01/01 00:00:00 になったの。 逆質問だけど、どんなエラーだったのか教えてください。 エクスプローラーとか、バックグラウンドで動いているシステムなどが、 フォルダをロックしていたら、失敗する だから、タイミングによって、成功したり失敗したりする 読み取りロックは、読み取り同士では共有できるけど、 書き込みロックは、その他すべてと共有できないから、失敗する確率が高い テキストファイルに設定できるストリームって何に使うんすか? テキストストリームの事なのかNTFSの代替データストリームの事なのか どちらなんだ 代替データストリームはテキストに限った話じゃないのでは ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる