- 1 名前:デフォルトの名無しさん mailto:sage [2022/02/13(日) 18:36:12.07 ID:LaQ04ZoE.net]
- 前スレ
PowerShell -Part 5 https://mevius.5ch.net/test/read.cgi/tech/1615994992/ 次スレは>>980が立ててね!!
- 792 名前:デフォルトの名無しさん mailto:sage [2023/04/17(月) 02:46:16.45 ID:dBG5z/eM.net]
- 入出力をちゃんと定義できてないからおかしな事になる初心者あるあるだな
- 793 名前:デフォルトの名無しさん mailto:sage [2023/04/17(月) 11:31:05.75 ID:udj2SRYX.net]
- 特定の深度だけ処理してみた
※$Sourceはフルパス指定であること param( [string] $Source, # $Sourceからの相対深度 [int] $RelativityDepth ) # パスを\と/で区切って配列化 $SourceDirSplit = $Source.Split([System.IO.Path]::DirectorySeparatorChar).Split([System.IO.Path]::AltDirectorySeparatorChar) foreach ($TargetDir in @(Get-ChildItem -LiteralPath $Source -Recurse -Directory)) { # パスを\と/で区切って配列化 $TargetDirSplit = $TargetDir.FullName.Split([System.IO.Path]::DirectorySeparatorChar).Split([System.IO.Path]::AltDirectorySeparatorChar) # 指定深度にあるDirを処理 if ($TargetDirSplit.Count -eq ($SourceDirSplit.Count + $RelativityDepth)) { # 一致したディレクトリを返す $TargetDir } }
- 794 名前:デフォルトの名無しさん mailto:sage [2023/04/19(水) 22:39:13.81 ID:CpwHPFTk.net]
- Start-ThreadJob や Register-EngineEvent のスクリプトブロックの中で
キャプチャされずにWrite-Output 相当の出力をする方法はないでしょうか パイプラインに流したいので Write-Host ではなく Write-Output したいです 別のプロセスを経由する方法は思いついたのですが残念過ぎますし ForEach-Object -Parallel のようにキャプチャされなければ良いのに function hogepiyo { begin { 処理本体はここで Start-ThreadJob しておく } process { … } end { … } clean { … } } なんちゃら | hogepiyo | ぽげむた のようにしたくて考えてます 要は入出力と処理を非同期にできれば他の方法でもありがたいです
- 795 名前:デフォルトの名無しさん mailto:sage [2023/04/20(木) 22:12:24.17 ID:dJqrvGvM.net]
- キャプチャとか何言ってるのかわからない
- 796 名前:デフォルトの名無しさん mailto:sage [2023/04/20(木) 22:40:35.29 ID:fUuxiSJs.net]
- PowerShellでフォーム作るの割と苦痛なんだけど何かデザインモードとかないの?
- 797 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 05:21:56.20 ID:ZJfuu8vu.net]
- Where-object多様するスクリプトに数万行のcsv食わせたら処理に1時間くらいかかる…
大量のデータ処理はWhere-object使うなってみかけたけど使わん方がいいのか
- 798 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 07:34:50.39 ID:TBBX4m6H.net]
- 件数が少ないことが確実な時しか使わない。
スクリプトだとほとんど foreach(){} 使ってる。 パイプライン処理したい場合でも &{} や .{} や function の process{} あるいは filter。
- 799 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 09:17:07.60 ID:kA/+t8w0.net]
- >>783
PowerShell Pro Tools https://ironmansoftware.com/powershell-pro-tools
- 800 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 11:30:54.75 ID:c3fakvC2.net]
- >>784
PowerShell スクリプトのパフォーマンスに関する考慮事項 ttps://learn.microsoft.com/ja-jp/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations?view=powershell-7.3
- 801 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 17:50:40.46 ID:4gKwO2KA.net]
- >>782
出力がコレクションにためられて Receive-Job が必要になるのを回避したい Start-ThreadJob の -StreamingHost オプションの Write-Output 版な感じ そんなオプションはないから回避方法を知りたい Start-TheadJobだけでなくイベントハンドラから出力する場合も同じ イベント飛ばせばいいかと思ったらハンドラがジョブ扱いされて頭抱えた どうすれば Receive-Job を必要とせずに Write-Output 相当の出力ができるのだろう
- 802 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 18:06:57.94 ID:xAAOLjx6.net]
- >>785
>>787 40万行処理するのに3時間かかったから作りなおすわ…
- 803 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 19:56:34.84 ID:6pSKsEtx.net]
- >>788
Jobである必要がないならRunspacePoolでできるんじゃね
- 804 名前:デフォルトの名無しさん mailto:sage [2023/04/21(金) 21:03:30.48 ID:Vzmd1cD+.net]
- >>786
おお、あるのか来週会社で使ってみる ありがとう
- 805 名前:デフォルトの名無しさん mailto:sage [2023/04/22(土) 10:34:00.20 ID:iFkcYPBt.net]
- function target
・入力を読み続ける ・最後に読んだ入力を1秒間隔で出力し続ける ・入力が q なら終了 処理遅延を無視した理想的な使用例が . { $s = Get-Date; 1; sleep 3; 2; sleep 3; 'q' } | target | % { '{0} {1}' -f (Get-Date) - $s, $_ } 0:00:00.0000000 1 0:00:01.0000000 1 0:00:02.0000000 1 0:00:03.0000000 2 0:00:04.0000000 2 0:00:05.0000000 2 となるような function target はどうすれば実現できますか 処理時間でずれていくのはもちろんかまいませんが 入力待ちにも出力を続ける具体例が知りたいです
- 806 名前:デフォルトの名無しさん mailto:sage [2023/04/22(土) 10:36:10.71 ID:iFkcYPBt.net]
- おっと間違い
(Get-Date) - $s でなく ((Get-Date) - $s) だ
- 807 名前:デフォルトの名無しさん mailto:sage [2023/04/22(土) 16:45:49.14 ID:3JkCsMe2.net]
- >>792
「qなら終了」が何を示すかによるが、powershellのパイプは途中で打ち切る事は原則できないと考えた方が良い。 (endブロックが呼ばれない不完全なハックならググれば見つかる) またパイプ処理の待機はpowershellのメインスレッドの待機という意味になるので、 そこに非同期イベントを介入させたい場合はそのイベント用の別スレッドを走らせておく必要がある。
- 808 名前:デフォルトの名無しさん [2023/04/22(土) 21:39:35.55 ID:81urZ/Lj.net]
- (New-Object -ComObject Shell.Application).NameSpace(10).MoveHere(ファイルパス)
上記の方法でファイルをごみ箱に移動する場合ファイルが1個なら問題ないんですが、 ファイルパスをを"z:\*"みたいにワイルドカードで指定するとなぜか ごみ箱でなくC:\Users\ユーザー名にファイルが送られてしまいます。 どうすればごみ箱に送れましょうか?
- 809 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 10:54:07.72 ID:ElcI27v7.net]
- >>794
q は出力スレッドの停止マークで、入力の最後も意味するつもりだった (その後の入力はない) という考えをくみ取って欲しくて例を付けたのだが伝わらなくて残念 パイプラインの中断にSelect-Object -First 1する話は知ってる ていうか本題から話をそらそうとしてません? 知りたいのはメインスレッド以外からプライマリパイプラインに出力する方法 パイプラインの次段に送るにはどうすればいいか具体例が欲しい
- 810 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 15:49:22.67 ID:fUzoPDLK.net]
- シェルスクリプトやPowerShell が遅いのは、
毎行、何かのプロセスを起動するからじゃないの? 多くはプロセスの起動時間だろう Ruby は、外部プロセスを起動しなければ、プロセスは1つのまま。 並行処理もあるけど grep は、1GB を1秒!
- 811 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 16:01:56.38 ID:vCOHFjdN.net]
- >>796
そもそもパイプは同期的にしか動かないので、次段でいくら細工しても上流が出力を起こしたタイミングに縛られる。 話を単純にするなら不規則な出力を受ける処理と一定間隔で出力する処理は分けるべきだろうね。
- 812 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 16:05:07.36 ID:fUzoPDLK.net]
- >>795
移動なら、robocopy のmov/move を使えば?
- 813 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 16:10:27.14 ID:n0NMvdBV.net]
- >>799
どうやればごみ箱に移動できましょうか?
- 814 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 16:33:01.94 ID:aISPDv4l.net]
- >>795
シェル名前空間はバグだか仕様だか判らない所があるから真面目に考えても無駄 もうそういう仕様と考えてファイルは1個1個送れば? ワイルドカードはgciで展開できるんだし
- 815 名前:デフォルトの名無しさん mailto:sage [2023/04/23(日) 17:57:33.46 ID:ElcI27v7.net]
- >>798
サブスレッドがパイプラインに書き込めば次段が動くんじゃないの?
- 816 名前:言い換えると >>792 のfunction targetは実現不可能ということ? []
- [ここ壊れてます]
- 817 名前:デフォルトの名無しさん mailto:sage [2023/04/24(月) 17:53:43.44 ID:cODz6Qqq.net]
- >>801
どうもありがとうございます。そうします。
- 818 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 01:01:33.91 ID:q0KJktEO.net]
- 最近この言語で書くことあるけど関数の呼び出しを最初に書かないとエラー起こすなんて知らなくて問題解決に時間がかかった
多分ほとんどの人が関数はメインの後に書きたいと思うんだけどファイル分けて呼び出したりしてるの?
- 819 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 07:59:40.97 ID:0OU27daL.net]
- >>804
> 多分ほとんどの人が関数はメインの後に書きたいと思うんだけど んなことはない 呼び出される方を前に書かなきゃいけないのは他の言語でも多いぞ
- 820 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 08:14:10.57 ID:Q567y34W.net]
- >>805
定義を上書きできる言語なら呼び出し順序に意味があると思うけど、そうじゃないならただの手抜き仕様
- 821 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 08:17:30.73 ID:0OU27daL.net]
- >>806
実行速度が速くなる、スコープが明確になる、などのメリットがあって敢えて採用されてるんだよ JSとかも古くからあるfunction構文は順序関係ないが今推奨されてるアロー関数だと前に書かなきゃだめだ
- 822 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 08:19:33.10 ID:0OU27daL.net]
- あとスパゲティを防ぐ効果があるというメリットもあるな
C言語だとそれを目的にプロトタイプを書かない人もいる
- 823 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 08:27:15.73 ID:h+X7r+oZ.net]
- 関数同士の依存関係が明確で前の関数が後の関数に依存しないなら初めてのコードを読みやすくなるというメリットもあるな
- 824 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 08:33:08.87 ID:TxIkuN+X.net]
- ホイスティングってJS以外であるの?
- 825 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 09:07:53.85 ID:qRrW+mkA.net]
- Java隆盛くらいの時代には関数はどこに書いても良いのが当たり前として定着したけど
関数型プログラミングでは関数宣言は変数や定数の宣言と同じようなものだからどうしても順序を意識せざるを得ない 順序の扱いを自動でやってくれる仕組みがホイスティングなんだけど、そのルールの分かりにくさやいやらしさが開発者に嫌われてJavaScriptのvarがletとconstに取って代わられた歴史がある
- 826 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 11:26:54.33 ID://VjHWfL.net]
- >>804
メインの部分をメイン関数として書いて実行時にメイン関数を呼び出すようにすればよいのでは?PowerShellはシェルとしても動くので実行時に先に関数が定義されていないといけないのは自然な動作のような気もする。
- 827 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 11:29:40.93 ID:Y1VsObgt.net]
- vbsは関数後書きでもokだよ
よしvbs使おう
- 828 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 11:43:20.51 ID:Xlw1eETD.net]
- >>812
begin process endブロック使いたいときに発狂しそうだな
- 829 名前:デフォルトの名無しさん mailto:sage [2023/04/25(火) 21:27:41.00 ID:RtJhGNCC.net]
- powershellでもclass内なら順序関係なくなるよ
- 830 名前:デフォルトの名無しさん mailto:sage [2023/05/04(木) 17:38:09.61 ID:spWJYsDj.net]
- 自分のコード見たら別に後から宣言してても実行できてるんだが
コマンドレットの定義だとホイスティングされるとかある?
- 831 名前:デフォルトの名無しさん mailto:sage [2023/05/04(木) 17:56:23.79 ID:P088Z0u/.net]
- >>816
どういうコード書いてんのよ
- 832 名前:デフォルトの名無しさん [2023/05/04(木) 21:18:57.29 ID:FdNSNO1e.net]
- >>816
古臭いと言われても、前に書いた方が無駄な混乱をさけられる。
- 833 名前:デフォルトの名無しさん mailto:sage [2023/05/05(金) 18:03:31.01 ID:gmBJZ0Nw.net]
- 動的言語は第一級関数のクロージャが多いから、
関数外で宣言したローカル変数が、関数内へ持ち込まれるので、 スコープが広くて、ヤバイ さらに、JS はホイスティングされるから、超ヤバイ ただし、Ruby の関数だけは第一級関数のクロージャではなく、 関数外で宣言したローカル変数は、関数内へ持ち込まれない だから他の言語よりも、圧倒的にバグらないので、初心者向き
- 834 名前:デフォルトの名無しさん [2023/07/08(土) 13:16:16.25 ID:UoEVlKLQl]
- 他人の権利を強奪して私腹を肥やす強盗殺人政治やってる論理もクソもないロクに勉強してない議員た゛らけ無能外道集団公明党と違って維新
は最低限の知的能力を有してる奴が多いのは橋下徹の意向で容赦なく知的能カの足切りやってる成果なんた゛ろうけど、いい年して玉遊ひ゛とか してる無能を讃えてみたり,日本に原爆落とした世界最惡のならす゛者國家の覇権主義に利用されてるウクラヰナ状態になるリスクを無視して 軍拡推進してみたり,危險極まりない原發推進すれは゛電気料金は下がるた゛のほさ゛きか゛ら鉄道のЗ〇倍以上もの非効率クソ航空機によって莫大 な石油無駄に燃やしてヱネ価格暴騰させて温室効果カ゛ス倍増させて氣侯変動させて災害連發させて貿易赤字に.そんなバカの象徴萬博を誇っ てみたり.騒音によって知的産業に威力業務妨害して壞滅させて原發とか笑わせるレヘ゛儿にまで曰本の技術カ低下させて.勉強妨害して犯罪 惹起しながら動物虐待は罰則強化しろ、子の虐待には金くれてやれた゛の,いつの間にか憲法の下の平等に反しないヘ゛一シックインカムも言わ なくなって社会分断惹起して治安惡化とか,頭は回るか゛古い教育制度による時代遅れの固定観念による思慮のなさは直情的な橋下徹由来かな
創価学會員は.何百万人も殺傷して損害を与えて私腹を肥やし続けて逮捕者まで出てる世界最悪の殺人腐敗組織公明党を 池田センセ─が口をきけて容認するとか本気で思ってるとしたら侮辱にもほどか゛あるそ゛! https://i.imgur.com/hnli1ga.jpeg
- 835 名前:デフォルトの名無しさん mailto:sage [2023/06/29(木) 13:26:04.42 ID:GLUt9X10.net]
- get-childitem select-object Full name,でownerを追加する方法はありますか?ご存知の方、ご教示願います。
- 836 名前:デフォルトの名無しさん mailto:sage [2023/06/29(木) 17:48:28.46 ID:xt/PffdC.net]
- >821
Get-ChildItemだけではowner情報は取れない、Get-Aclで情報取得する必要がある 組み合わせで良ければ以下の様にSelect-Objectでプロパティ追加すれば出来る Get-ChildItem|Select-Object FullName,@{n="Owner";e={Get-Acl $_.fullname|% {$_.Owner}}}
- 837 名前:デフォルトの名無しさん mailto:sage [2023/07/07(金) 19:48:22.82 ID:5l+s6JZK.net]
- Outlook を起動してメールを送りたいのですが
本文のメールのフォントサイズや色の指定が一切無視されます。 Outlook 側の設定なのか、コードが悪いのかもよくわからず。。。 スレ違いならすいません =================== $outlook = New-Object -comObject Outlook.Application $mail = $outlook.CreateItem(0) $mail.Subject = "件名テスト" $mail.HTMLBody = "<html>&
- 838 名前:lt;head><style type='text/css'>
body {font-size:11; font-family:Meiryo UI;} </style></head><body> ああああ<span style='text-decoration:underline; text-decoration-color:red;'>いいいい</span>ううう<br> </body></html>" $inspector = $mail.GetInspector $inspector.Display() #$mail.Send() =================== 上記のコードだとメイリオは設定されますが、フォントサイズは8.5になるし下線は黒色になります。 なにとぞご教示お願いします [] - [ここ壊れてます]
- 839 名前:デフォルトの名無しさん mailto:sage [2023/07/10(月) 00:01:29.03 ID:pvSg+WfU.net]
- font-sizeの値に単位が無いから無視されてんじゃね
- 840 名前:デフォルトの名無しさん mailto:sage [2023/07/10(月) 03:13:05.95 ID:ixw20e1S.net]
- >>824
試したはず・・・と思いつつも確認したら普通に変更されました!!! 11px で確認したのかもしれません。11pt と書いたら普通に反映されました ありがとうございます ただ下線は相変わらず赤色にならず、黒色のままです。 #FF0000 も試したけど変わらず・・・ どうやら text-decoration-color がそもそも使えないようでした。 さささ<span style='text-decoration:underline; color:red;'>ししし</span>すすす<br> とやったら文字も赤くなりましたが下線も赤くなりました。 Outlook に使える html の仕様との戦いな気がしてきた これはどこで尋ねたら・・・
- 841 名前:デフォルトの名無しさん mailto:sage [2023/07/10(月) 10:11:13.02 ID:CzqO5vr+.net]
- 後はstyle属性をシングルクォーテーションで括ってるのが気になった
全体の括りをシングルにして属性値をダブルに変更で動くと思うよ
- 842 名前:デフォルトの名無しさん mailto:sage [2023/07/10(月) 10:51:54.81 ID:ixw20e1S.net]
- シングルとダブルは変わりませんでした…
実際はPowerShellでメール本文内に変数を当てこむので シングルのままでいこうと思います あと下線だけ赤色は私の勘違いでした 赤下線の時は文字も赤くして問題なかったのでとりあえず解決しました お手数おかけしました ご助言くださった方ありがとうございました
- 843 名前:デフォルトの名無しさん mailto:sage [2023/07/13(木) 11:56:03.10 ID:cnmTEsiX.net]
- 二週間ほど前に自分で調べて書いたのに、どうやって書いて動かしたのか全く思い出せなくて困ってます
自分で自分が信じられないんですが、教えてください。 やりたいこと:Read-Hostで指定したフォルダに存在するフォルダを取得し、各フォルダに指定したファイルをコピーする 引っかかっている点: 1)$input = Read-Host "コピー先フォルダを指定" たとえばここでcopyと入力。規定のフォルダがC:\作業とする。 入力の結果、c:\作業\copyとして、ここにあるサブフォルダを取得したいので $inputをc:\作業\copyにしたい。 2)Get-ChildItem でディレクトリ名のみ取得するには? それでforeachでやってたと思うんですが・・・。
- 844 名前:デフォルトの名無しさん mailto:sage [2023/07/13(木) 13:50:42.52 ID:K8IsBXo8.net]
- Get-ChildItem -LiteralPath ([IO.Path]::Combine("C:\作業", (Read-Host "コピー先フォルダを指定"))) -Directory -Name
- 845 名前:デフォルトの名無しさん mailto:sage [2023/07/13(木) 17:51:09.66 ID:cnmTEsiX.net]
- >>829
わー初見のコード でもおかげでなんとかできました。ありがとう。
- 846 名前:デフォルトの名無しさん mailto:sage [2023/07/14(金) 04:02:22.77 ID:vOCFwCnb.net]
- 多分いままで書いてたコードはこれ
# 規定のフォルダのパスを作成 $parent = join-path 'c:\作業' $input # 上記パスのサブフォルダ作成 $names = ls -pspath $parent -di | % name 下記はエイリアス(関数の別名) ls := get-childitem % := foreach-object
- 847 名前:デフォルトの名無しさん mailto:sage [2023/07/14(金) 04:02:59.81 ID:vOCFwCnb.net]
- # 上記パスのサブフォルダ作成
↓ # 上記パスのサブフォルダ名を取得
- 848 名前:820 mailto:sage [2023/07/18(火) 17:12:35.63 ID:jBHsPJa3.net]
- >>822
遅くなりました。 set-location -pathで場所を指定したら、指定したフォルダのownerを取得できました。ありがとうございます。 get-Childitem -recruse -file ┃select-Object directoryName ,name ,extension ,Length Creationtime, lastACCESStime ,lastwriteTime, fullname ┃Export‐csv ‐Encodeing default xxx.csv と一緒にできなかったのが悔やまれます。
- 849 名前:デフォルトの名無しさん mailto:sage [2023/07/18(火) 18:02:52.05 ID:uMqw2ex7.net]
- そういう時はadd-memberするんだよ
- 850 名前:デフォルトの名無しさん mailto:sage [2023/07/18(火) 20:02:12.51 ID:x3+Ehzia.net]
- >>822の何がだめで、あるいは何が分からなくて、そのコマンドに組み込めなかったのか分からんな。
起点ディレクトリ自体の情報もCSVに含めたい、って事なのかな。
- 851 名前:デフォルトの名無しさん mailto:sage [2023/07/18(火) 22:45:48.56 ID:BpIlHiPB.net]
- powershellの学習曲線は険しい
本人が納得したならもうそれでいいだろう
- 852 名前:820 mailto:sage [2023/07/19(水) 08:31:15.42 ID:wWAjwZqt.net]
- >>835
そうです。
- 853 名前:デフォルトの名無しさん mailto:sage [2023/07/19(水) 15:47:04.50 ID:mqKqy4GV.net]
- ならこんな感じで。
$dirPath = "起点ディレクトリのフルパス" [IO.FileInfo]::new($dirPath) | %{$_; $_ | Get-ChildItem -Recurse -File} | Select-Object DirectoryName, Name, Extension, Length, CreationTime, LastAccessTime, LastWriteTime, FullName, @{N="Owner";E={($_ | Get-Acl).Owner};} | Export-Csv -Encoding Default xxx.csv CSVの出力先がフルパスなら、Set-Locationはいらない。
- 854 名前:820 mailto:sage [2023/07/24(月) 18:16:28.42 ID:yY3fBN5A.net]
- >>838
ありがとうございますm(_ _)m とりあえずownerを取得できました。列の入れ替えはPowerQueryで対処します。 neme,Extensio,owner,...したかったのですが。
- 855 名前:デフォルトの名無しさん mailto:sage [2023/08/02(水) 23:31:49.70 ID:8Lc0dkYb.net]
- Pythonでやったら楽なのに…と思う処理も他のメンバーに配る可能性を考えると泣く泣くpowershellでやることになる
嫌いな言語ではないけど凝った処理を書こうとすると見た目の癖が強いソースコードになりがち
- 856 名前:デフォルトの名無しさん mailto:sage [2023/08/05(土) 08:55:12.86 ID:4wFerhHK.net]
- Pythonは見た目の癖が強くないとでも?
- 857 名前:デフォルトの名無しさん mailto:sage [2023/08/05(土) 09:35:04.11 ID:wvUeqD5z.net]
- 泣く泣くpowershellに草
- 858 名前:デフォルトの名無しさん mailto:sage [2023/08/06(日) 22:29:47.72 ID:5CExyS7F.net]
- 質問なのですがパイプラインの結果を関数に渡して先頭からk番目を取り出すには一体どうすればorz
やりたいことはパイプラインの結果を検証する処理をサブルーチン化したい(k番目を取り出すのはその第一歩) とりあえず書いたがうまく行ってないやつ: function Test-RegEnt($reg_query_result, $exp_type, $exp_value) { $reg_query_result | Select-Object -Index 2 } Write-Output ("Test_A1:" + ($result | Select-Object -Index 2)) # 2行目が意図通りselectされる(" RegisteredOwner REG_SZ Admin") $result2 = Test-RegEnt($result, 'REG_SZ', 'Admin') Write-Output ("Test_A2:" + $result2) # A1と同じ結果になるかと思いきや、'Admin' になる
- 859 名前:デフォルトの名無しさん mailto:sage [2023/08/06(日) 22:31:40.76 ID:5CExyS7F.net]
- 先頭3行抜かしましたorz
$result = reg query 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion' /v 'RegisteredOwner' $cnt = 0 $result | ForEach-Object{ "TEST[$cnt}:" + $_; $cnt++ } この次に>>843のコード。
- 860 名前:デフォルトの名無しさん mailto:sage [2023/08/06(日) 22:48:34.72 ID:5CExyS7F.net]
- んまーなんかこれだとうまく行ったけんども思ってたのと違う……
function Test-RegEnt($exp_type, $exp_value) { $Input | Select-Object -Index 2 } $result = reg query 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion' /v 'RegisteredOwner' $cnt = 0 $result | ForEach-Object{ "TEST[$cnt}:" + $_; $cnt++ } Write-Output ("Test_A1:" + ($result | Select-Object -Index 2)) $result2 = ($result | Test-RegEnt('REG_SZ', 'Admin')) # パイプラインの結果を引数ではなくパイプで渡す Write-Output ("Test_A2:" + $result2) 実はパイプラインの結果(オブジェクトの配列)は関数引数に渡せなかったりするので
- 861 名前:?
つなみにfunctionの引数部分で [array]$reg_query_result としてみてもうまく行かなかった。 [] - [ここ壊れてます]
- 862 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 03:16:48.48 ID:SSXgsNNw.net]
- 文法が違う。
Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin' とか Test-RegEnt $result 'REG_SZ' 'Admin' とか。 または function Test-RegEnt { Param ( [Parameter(ValueFromPipeline=$true)] [string] $reg_query_result, [string] $exp_type, [string] $exp_value ) Begin { $cnt = 0 } Process { $cnt++ $idx = $cnt - 1 if ($idx -eq 2) { $reg_query_result return } } } $result | Test-RegEnt -exp_type 'REG_SZ' -exp_value 'Admin'
- 863 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 06:50:14.57 ID:L1yQ0BJe.net]
- >>846
レス㌧クス $Input利用(>>845)とBegin { } Process { }利用の違いはわかりた $resultが数億オブジェクトだったりしたら後者の方がパイプラインがスムーズに流れてよさげ(未検証 一方、 >実はパイプラインの結果(オブジェクトの配列)は関数引数に渡せなかったりするので?(>>845) については関数の呼び出し箇所が $result | Test-RegEnt -exp_type 'REG_SZ' -exp_value 'Admin' # (1) OK Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin' # (2) NG (エラー) やったから、これは「パイプラインの結果は関数引数には渡せない」((1)のように書くしかない)ということでFA?
- 864 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 06:54:08.66 ID:FZVMVghc.net]
- Select-ObjectのSkipとFirst使えばできるのでは?
- 865 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 06:56:57.16 ID:FZVMVghc.net]
- 関数でやりたいという要件を見落としていた
- 866 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 07:04:28.71 ID:FZVMVghc.net]
- >>843
> $result2 = Test-RegEnt($result, 'REG_SZ', 'Admin') $result2 = Test-RegEnt $result 'REG_SZ' 'Admin' でやりたいことはできるのではないでしょうか
- 867 名前:デフォルトの名無しさん mailto:sage [2023/08/07(月) 22:40:57.49 ID:SSXgsNNw.net]
- パイプラインと引数のどちらでも動くようにしたいなら
function Test-RegEnt { Param ( [Parameter(ValueFromPipeline=$true)] [string[]] $reg_query_result, [string] $exp_type, [string] $exp_value ) Begin { $cnt = 0 } Process { foreach ($item in $reg_query_result) { $cnt++ $idx = $cnt - 1 if ($idx -eq 2) { $item break } } } } あくまでシンプルめのサンプルなんでSelect-Object -Index 2と全く同じ挙動とか期待しないように。 ※作りこむならパイプが繋がってるのかチェックして分岐の処理書いたりする。 なお、大量のデータをパイプラインに流すのはお勧めできない。 パイプラインは途中での打ち切りとか難しいし、 結局は普通にループ処理書いた方が速いし制御しやすいし分かりやすい事が多い気がする。
- 868 名前:デフォルトの名無しさん mailto:sage [2023/08/10(木) 07:01:52.35 ID:3iQsMBl9.net]
- レス㌧クス、しかしながら大量データを引数で関数に渡すのはメモリ消費量、応答速度ともに悪くなることがわかったからやめるわサーセン;;;
どういうことかというと、bigfile.txtが(1行何か書いたいた後 Ctrl+A Ctrl+V Ctrl+V を22回反復とかで作った) 4194305行の巨大なテキストファイルだったとして、 function Test-FileContent([string[]] $lines) { $cnt = 0; foreach ($line in $lines) { $cnt++; Write-Host "cnt=" $cnt } } $lines = Get-Content .\bigfile.txt # (1) Test-FileContent($lines) # Get-Content完了後の結果を引数で渡す とするとお、「cnt= 1」が表示される前に(1)で永劫の時間待たされるますが、 function Test-FileContent() { $cnt = 0; foreach ($line in $Input) { $cnt++; Write-Host "cnt=" $cnt } } Get-Content .\bigfile.txt | Test-FileContent # Get-Contentが読んだら即パイプで渡す とすると*即座に*「cnt= 1」以降のカウントが始まる
- 869 名前:デフォルトの名無しさん mailto:sage [2023/08/10(木) 07:07:45.76 ID:3iQsMBl9.net]
- つなみに
>$resultが数億オブジェクトだったりしたら後者の方がパイプラインがスムーズに流れてよさげ(>>847) も検証すた、 >>847のレスポンスが即時のコードと似通っているが関数内でBEGIN { } PROCESS { }でなく$Inputをforeachループで回した場合、 すわなち function Test-FileContent() { $cnt = 0; foreach ($line in $Input) { $cnt++; Write-Host "cnt=" $cnt } } Get-Content .\bigfile.txt | Test-FileContent とすると、、「cnt= 1」が表示される前に永劫の時間待たされる、、、 というわけで、パイプライン(の後段まで)に大量のデータを無駄に流すなというのは真やが 生じてしまった大量のデータはむしろパイプラインにしか流さないのが正義……
- 870 名前:デフォルトの名無しさん mailto:sage [2023/08/10(木) 07:10:57.08 ID:3iQsMBl9.net]
- >>852の肝心のところに誤記が合ったスマンヌorz
*即座に*「cnt= 1」以降のカウントが始まるコードは正しくはこれ↓ function Test-FileContent() { BEGIN { $cnt = 0 } PROCESS { $cnt++; Write-Host "cnt=" $cnt } } Get-Content .\bigfile.txt | Test-FileContent
- 871 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 18:46:06.42 ID:I7dwFhkG.net]
- パイプの利点は個数を意識しなくて済むことだけど中断が一切できないしデメリットの方が多い
よっぽどの事情でもない限りコマンドレット自作しても遅いだけで良い事なんて1つもない 公式のselect -firstなんかはパイプの流儀に従ってないから似た事をしようとしてもあれ?って自らの間違いに気付くんだよ powershellの深遠を覗くとそのいい加減さにガッカリするだけ
- 872 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 19:17:06.70 ID:SL3m3m5F.net]
- 一番の利点はメモリの節約です
- 873 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 19:30:40.13 ID:I7dwFhkG.net]
- メモリなんて遅さで相殺される
powershell + 大量データ = 遅くて不採用
- 874 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 19:42:42.98 ID:bAYgNtyZ.net]
- >>857
使いどころを履き違えるとそうなる
- 875 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 19:56:15.04 ID:I7dwFhkG.net]
- >>858
パイプに希望を見てるのかな その認識では近く失望させられるだろう
- 876 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 20:07:52.72 ID:PQblbJTG.net]
- 一番良いのは、Windowsを使わない
これにかぎる こんなクソなOSを世界中から捨てるべき
- 877 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 20:09:59.59 ID:SL3m3m5F.net]
- Windowsは汎用事務処理端末としては競合なしだ
- 878 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 20:27:11.32 ID:SL3m3m5F.net]
- メモリ効率とスループットは交換できるようなものではない
手軽さが不要ならPythonでも使っておけばいい
- 879 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 21:36:23.24 ID:55Ub7uv5.net]
- いまだにPowerShellがWindows専用だと思ってるアホを真っ先に捨てるべき
- 880 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:05:41.72 ID:FP8PIUGD.net]
- で>>843の質問に戻るのですだが、動かなかったのは単純だが根本的な誤解してたのが原因……
C/C++と同じだろうというつもりで >$result2 = Test-RegEnt($result, 'REG_SZ', 'Admin') という呼び出し方に書いたが、これだと「Test-RegEntの第一引数$reg_query_resultに「配列」@($result, 'REG_SZ', 'Admin')を渡す」という意味になる ので、関数内で >$reg_query_result | Select-Object -Index 2 とやったら当然そのindex=2の要素 'Admin' が関数の出力となってた、というしくみ
- 881 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:07:08.58 ID:FP8PIUGD.net]
- 正しくは>>846式に
>Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin' またはその省略表記としては >Test-RegEnt $result 'REG_SZ' 'Admin' # カンマ区切りではなくてスペース区切り にせねばならなかった ことがわかったorz 止むにやまれない事情で昨日一日で1500行書いてデバッグしたらその過程でわかった|||。n_
- 882 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:11:54.59 ID:FP8PIUGD.net]
- あと他のスクリプトをincludeするときの欠き方が気づかないとわかりにくい……
util.ps1 を同じフォルダにある someapp.ps1 からインクルードする場合は '.\util.ps1' ではダメで、 .'.\util.ps1' にしないとutil.ps1で定義した何物も呼び出せないorz ここで先頭の「.」はutil.ps1のスクリプトスコープを呼び出し元のスコープと同じにするという意味やがちょう紛らわしい……
- 883 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:20:54.21 ID:FP8PIUGD.net]
- あと関数内においては代入文、[void]にキャストした文、if文とかの条件式 を除く全ての文が出力を持つ、
という仕様のせいで危うく恐ろしいバグを作り込むところやった;;; function Show-ErrDlg($msg) { $wsobj = new-object -comobject wscript.shell $wsobj.popup($msg, 0, 'エラー', 0 -bor 16) }
- 884 名前:function Test-Equipment1() {
$result = (何かのテスト) if (!$result) { Show-ErrDlg('何かのテスト failed.') } return $result } でとするとテストが失敗したときも [] - [ここ壊れてます]
- 885 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:25:27.54 ID:FP8PIUGD.net]
- if (!(Test-Equipment1) { exit 1 }
(テスト正常終了の表示処理) でテスト正常終了の表示が出るorz これは何でかというと$wsobj.popup($msg, 0, 'エラー', 0 -bor 16) 」がクリックされたボタンの番号を出力する結果、$resultがまたしても配列 @( (「なんかのテスト」の結果), ($wsobj.popup()でクリックされたボタンの番号) ) となりこれが Test-Equipment1() の戻り値となり、それをif文で評価したら最後の要素
- 886 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:27:54.43 ID:FP8PIUGD.net]
- (OKボタンのコード6)と評価されるため、!6なので常に偽になるというしくみ、、、、
こう修正すたら直った function Show-ErrDlg($msg) { $wsobj = new-object -comobject wscript.shell [void] $wsobj.popup($msg, 0, 'エラー', 0 -bor 16) # [void]付ける } わかるかこんなもん…… および原理的にlint的な機械的チェックもできない……
- 887 名前:デフォルトの名無しさん mailto:sage [2023/08/11(金) 23:35:32.35 ID:FP8PIUGD.net]
- これはデフォルトで出力無しとして、
なんかの接頭辞を付けた文だけが結果がパイプに出力されるるようにする仕様であるべきだった希ガス (出力が無いというミスはすぐ気づける てかWrite-Outputを省略可能としているのがそもその誤り…… ※ 個人の感想です いっぱい連投したがTeamsのつもりでShift+Enterしたら投稿されてしまったせいやスマンヌorz いじょ
- 888 名前:デフォルトの名無しさん 転載ダメ mailto:sagete [2023/08/12(土) 00:58:59.52 ID:H+b+A9qi.net]
- ============================
function Hoge([int]$num) { echo "Debug" return ($num + 1) } $a = Hoge(1) echo $a ============================ こうすると $a には Debug と 2 の2つが入る ============================ function Hoge([int]$num) { .{ echo "Debug" } | Out-Null return ($num + 1) } $a = Hoge(1) echo $a ============================ こうすると $a には 2 の1つしか入らない 不要なところは 「 .{ ~~~ } | Out-Null 」で表示を抑制したら楽になるかも
- 889 名前:デフォルトの名無しさん mailto:sage [2023/08/12(土) 01:19:17.04 ID:DbL0Mu2X.net]
- >>843に言える事はパイプで何番目とかいう考えは捨てた方がいい
パイプは途中で処理を打ち切る機能が欠落してるから何番目だけに用があろうが全ストリームを読み終わるまで終わらない
- 890 名前:デフォルトの名無しさん mailto:sage [2023/08/12(土) 08:19:31.33 ID:IRt4i0hm.net]
- ほぼ誤差だが |Out-Null より $null= で処理した方がパフォーマンスがよく、可読性も高い
- 891 名前:デフォルトの名無しさん mailto:sage [2023/08/12(土) 08:23:13.14 ID:ueiwXwrP.net]
- PowerShell スクリプトのパフォーマンスに関する考慮事項
https://learn.microsoft.com/ja-jp/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations
- 892 名前:デフォルトの名無しさん mailto:sage [2023/08/12(土) 22:00:12.59 ID:pISu+im0.net]
- >>872
わかりた パイプラインの打ち切りは、実現方法はあるが円満な解決方法はなさげ(どれもこれもなんかしらのミソがつく パイプで$n番目、というだけならSelect-Objectしたらv3以降ならn+1番目以降を打ち切ってくれる $n = 2 Get-Content .\bigfile.txt | Select-Object -Index $n | Foreach-Object { Write-Output "cnt=${n}: $_" } # bigfile.txtが1億行あっても瞬時に戻って来る が、これは「Select-Object -Index ~」部分を関数化したら元の木阿弥になる function Select-Nth($n) { $Input | Select-Object -Index $n | Foreach-Object { Write-Output "cnt=${n}: $_" } } Get-Content .\bigfile.txt | Select-Nth(2) # bigfile.txtを1億行全部読み込んでからおもむろに出力する 構文的に$_を使った関数やフィルタとしては書けない データを見て条件が成立したら打ち切り、というのになるともっとマンドクセ…… https://winscript.jp/powershell/308
|

|