【最強CUI】PowerShell -Part 2 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
>>624
> PSVersion 2.0 って、古いな
Windows 7 の標準装備だから会社によっては今でもその縛りがあるところは珍しくない むしろwin10なのに5.1は古い
6.01入れちまえ 標準で入ってるから使うんであって
わざわざ入れるなんて許されない
それがPowershellの掟 2.0でも問題ないように勉強しつつ、案件が始まったら最新版のインストールを駄目元でお願いする感じ ファイルの最後の文字のみ読み込んで
例えば最後の文字が
〇〇てすと
だったら
てすと
に置換して元から"てすと"だったそのままにしたいんだけどどうすればできますか?
ただし最終行が"てすと"じゃなかった場合は"てすと"を追記したいです
個人的にはループ処理で最終行から読み込んで意図した文字列なら置換って事がやれればいいと思ってます
※バージョンは2.0でお願いします! Ruby で作った
text = File.read ARGV[0] # 引数はファイル名
ary = []
# 文字列を1行ずつ、配列に入れる
text.each_line{ |line| ary << line }
p ary
# 戻り値は、置換が行われたときはレシーバ自身、置換されなかったときはnil
if ary[-1].sub!(/〇〇てすと$/, 'てすと')
# 処理なし。レシーバ自身を変更する
elsif /てすと$/ !~ ary[-1] # てすと で終わらない
ary[-1] += 'てすと'
else
return
end
p ary[-1]
File.write(ARGV[0], ary.join) >>633
ここPowershellスレなんだが… >632をなんとなく作ってみたんですけど、
最後に出力された文字列だけを置換しての部分がうまくいかない
置換自体は出来るんだけどその部分だけ文字列に書き込む方法が分からん。。。
(Get-Content D:\test\a.txt)[(Get-Content D:\test\a.txt).length..0] | Foreach-Object {
if( $_.length ){
if(!($_ -like "*てすと*")){
Add-Content -Path D:\test\a.txt -Value "てすと"
break
}
$_ -replace ".*てすと.*", "てすと"
break}
} >その部分だけ、文字列に書き込む方法が分からん
Ruby でも、ファイルを読み書き両用で開くと、
現在のシーク位置を、あれこれ移動しないといけないから、非常にややこしい。
シーク位置を変数に入れておいて、あれこれ考えるのは、ややこしい
だから、テキスト全体を改行区切りの配列に入れて、最後の行だけを変更してから、
全部を書き込む方が簡単
633 では、そうしている 趣旨に合っているかな?
$list=Get-Content sample.txt
$text="てすと"
foreach($line in $list){
if([string]::IsNullOrEmpty($line)){$line=$text}
$str=$line.Substring($line.length-3)
if($str -eq $text){ $newline=$str}
else{ $newline=$line }
$newline
} 再度
$list=Get-Content test.txt
$text="てすと"
foreach($line in $list){
if([string]::IsNullOrEmpty($line)){$line=$text}
$str=$line.Substring($line.length-3)
if($str -eq $text){ $newline=$str}
else{ $newline=$line }
$newline
}
if($str -ne $text){$text} ぱわーしぇる風にパイプかつメモリ最小で作ってほしーなんつって つーかバッチファイルスレで似たような質問してたアホだなこいつ >>639
いいんだけどこれだと空白行全部"てすと"になっちゃてね? そうしてる。
空白行は空白のままでよかったんだ
じゃIFのところだけ書き換え
$list=Get-Content test.txt
$text="てすと"
foreach($line in $list){
if(-NOT [string]::IsNullOrEmpty($line)){
$str=$line.Substring($line.length-3)}
if($str -eq $text){ $newline=$str}
else{ $newline=$line }
$newline
}
if($str -ne $text){$text} 考えたらこれだと文字数が3文字未満だとエラーになるな
ねむいが・・書き換えてみるかな 今度はどうだろう
$list=Get-Content test.txt
$text="てすと"
foreach($line in $list){
$newline=$line
if($line.length -gt 2){
$str=$line.Substring($line.length-3)
if($str -eq $text){ $newline=$str}
}
$newline
}
if($str -ne $text){$text} >>646
最終行だけてすとじゃなくてその上にてすとの文字列が有るとそのあと全部てすとになっちゃうね こんなもんかね
psv2.0に配列のcountあったっけか
$file = "test.txt"
$text = "てすと"
,@(Get-Content $file)|%{
foreach($i in 0..($_.count-1)){
if($i -eq ($_.count-1)){
if($_[$i] -like "*$text"){
$text
}else{
$_[$i];$text
}
}else{
$_[$i]
}
}
}|Out-File $file >>641
あっちは、「最終行」じゃなくて「空行を除く最終行」だったからちょっと面倒だ >>647
なんと、寝ぼけてやってちゃだめだな。
あとで見直すわ PowerShellコード可読性低すぎワロタwww時代はC#ですわ
Add-Type -TypeDefinition @"
using System.IO;
using System.Text.RegularExpressions;
public class Hoge {
private static readonly Regex r = new Regex(@"[^\n]*てすと$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant);
public static void ReplaceLastTest(FileInfo file) {
string s = File.ReadAllText(file.FullName);
s = r.Replace(s.TrimEnd(), string.Empty) + "てすと";
File.WriteAllText(file.FullName, s);
}
}
"@
[Hoge]::ReplaceLastTest((Get-ChildItem ./test.txt)) >>651
PSなら書く必要もないもの多過ぎ
ついでに普通の環境じゃ編集の補助まったくないだろ >>648や>>646のほうがよっぽど無駄なコード書いてるじゃんwww
ループインデックスとか久々に見たわwwwwベタループも条件分岐もくっそ読みにくいしwww
編集の補助ってインテリセンスの事ならこの程度のコードに必要ないだろw
つかpowershellerならVSCodeとっくに入っとるやろwww
C#もサポートされとるやんけwwww >>648
これだと"てすと"の後に無駄な空行があるとその無駄な空行の後に"てすと"って出力されちゃうね エディタすら選べない様な残念な環境で頑張るのがPSですから
ってのは置いといてadd-typeで強引に解決するのは割と好き >>654
最初の条件では空行を無視するとか書いてないけど >>653
C#の別ファイル書いてadd-typeの中にコピペすんの?
それメンテナンス性最悪だよな つうかこれでええやんwwww
誰だよC#とか言ったアホwwwww
function Update-LastTest ([IO.FileInfo]$file) {
$s = Get-Content $file | Out-String
$s = ($s.TrimEnd() -replace '[^\n]*てすと$', '') + 'てすと'
$s | Out-File $file
}
Update-LastTest (Get-ChildItem ./test.txt) 何言われようと、めげずに
どうでしゃろ
$list=Get-Content test.txt
$text="てすと"
foreach($line in $list){
$newline=$line
if($line.length -gt 2){
$str=$line.Substring($line.length-3)
if($str -eq $text){ $newline=$str}
else{$newline=$line}
}
$newline
}
if($str -ne $text){$text} >>658
あれ?
要求されてる仕様の理解が私とちがうな
どっちだろう? ABCDてすと => てすと
XYX123 => XYX123
てすとのてすと => てすと
てすとのabc => てすとのabc
みたいな要望じゃないかな? 2回実行したら全部の行がてすとになって区別付かなくなるけどそれでいい? >>662
>>632の質問投げた本人ですけど最後はてすとでいいです
つまり
ABCDてすと => てすと
XYX123 => XYX123
てすとのてすと => てすと
てすとのabc => てすと
空行 => なにもしない >>664に追記すると最後"だけ"を置換したいんです
途中に"〇〇てすと〇〇"
みたいな感じでてすとってワードが含まれていてもそれは無視したいんです 確認ですが
てすとのabc => てすと
これあってます?
これだと単に文字列 "てすと" が含まれていたら "てすと" と
出力するように思うんですが。 >>632
ごめんこれ質問が悪かったです
最終行が"てすと"ならじゃなくて最後の空行じゃ無い文字列に"てすと"が含まれていなかったら"てすと"を追記したい
が正しい これはどうでしょう。
行に"てすと"という文字列が含まれていたら"てすと"だけを出力
含まれていなければ、そのまま出力
最後の行に"てすと"が含まれていなければ、その行はその出力し
つぎの行に"てすと"を追加
結果は$newlistに出力
function newfile{
param($text="てすと")
process{
if($_.ToString().Contains($text)){$newline=$text}
else{$newline=$_}
$newline
}
end{ if( -NOT $newline.Contains($text)){$text} }
}
$list=Get-Content ファイル指定
$newlist=$list|newfile さいごに空の行もあり得るわけだ。<=これは入れていない
とするとそのはんていを1行追加するようだな。 これだから日本語の仕様書は役に立たないって言われるんだな
テストケースを10個ぐらい書いてくれないと伝わらないパターンだ
コーディングはそれから始めても遅くない 最後の空白行orNull行の判定もいれてみたんだけど
function newfile{
param($text="てすと")
process{
if($_.ToString().Contains($text)){$newline=$text}
else{$newline=$_}
$newline
}
#end{ if( -NOT $newline.Contains($text)){$text} }
end{ if(-NOT($newline.Contains($text) -or [string]::IsNullOrWhiteSpace($newline)) ){$text}}
}
$list=Get-Content 入力ファイル
$newlist=$list|newfile あってるかな?
あとは >>658 の方が綺麗なのを書いてくれることを期待。 >>674
空行は置いといて、最終行以外のとこに”てすと”が入ってても書き換わってしまうが
ただそれが望んだ動作かもしれん
もう分からんw >>676
"てすと"という文字列を含む行は、"てすと"という文字列に置き換える
そうですよ。 >>677
>>665と矛盾してると思うが
"最後だけを置き換えたい" で行の最後か文章の最後か分からんが、
てすとのabc => てすと
がOKなら行の最後じゃない、なら文章の最後だけって事じゃね?
なんか論理パズルやってる気になってきたなw >>676
最後に出てくる"てすと"以外は"てすと"があっても置き変えたくないです
あくまで最後だけ置き換えてください
>>677
置き換えないでそのままでいいです >>677
あー間違えた最後に出てくる"てすと"以外は"そのまま"でいいです >>679
あ、来た
それと最後の空行はどうなの?
@"
aaa
bbbてすと
"@
が元ソースだとして
@"
aaa
てすと
"@
@"
aaa
bbbてすと
てすと
"@
@"
aaa
てすと
"@
の3パターンあるが、どれ? >>681
一番最初がいいですね
↓
@"
aaa
てすと
"@ >>682
OK,やっと仕様が決まったね
めでたい >>679
最後に出てくる"てすと"という意味ですが、したのようなとき
"てすと"を含む最後の行は5行目という意味ですか?
1行目 abmてすとxyz
2行目 1239xxxx
3行目 yyyyyてすと
4行目 xxxxyyてすとyy
5行目 てすとuuuu <== "てすと"を含む最後の行
6行目 zzyyvv
7行目 練習123 >>684
その場合だと7行目を判断して"てすと"以外の文字列なので"てすと"を追記してください。 >>684
君も読解力に問題あるぞw
途中の行は無視でしょ、「"てすと"を含む最後の行」なんて君しか言ってない
5行目はそのままで、8行目に"てすと"が加わるんでしょ >>685
追記とは
8行目に"てすと"という文字列の1行ができるでよろしいですか? はっきり言って>>665が非常に分かりづらい
"最後"って表現は何とかしてくれ >>689
語彙が足らなくてごめんなさい。
最後っていうのをなんて伝えていいのかよくわからなかった
最終行っていうのも違うし、最後の文字列が入ってる行って言えばよかったんかな… >>691
空行っていうのもなんか曖昧というか例えばスペース一個あって改行したらそれも空行だし >>692
それははっきりした方がいいと思うよ。
一番最後の行が、スペースとしたとき
スペースとは、空白文字がありうるのか、nullなのかなど。 >>688
ところであっちのスレと同一人物?
BATでも解決してたはずだけど、なんでまた同じ質問をこっちに? 仕様があいまい
最後と言う言葉があいまい。
全体の文章の最後なのか、最終行を指すのか、どちらか分からないから
最終行だけがチェック対象なのか?
それとも、最終行以外も対象になるのか? >>632
>最終行が"てすと"じゃなかった場合は、"てすと"を追記したいです
これも、最終行が改行で終わっている場合と、終わっていない場合で、動作が変わる
abc\n → abc\nテスト
abc → abcテスト
上は、最終行の次の行に追加されるけど、
下は、最終行に追加される $path = "Documents\hoge.txt"
$text = "てすと"
$file = @(Get-Content $path)
for($i = $file.count; $i -ge 0; $i--)
{
if($file[$i] -match "^\s*$")
{
continue
}
if($file[$i] -match ".*$($text).*")
{
$file[$i] = $text
} else {
$file[$i] += "`n" + $text
}
break
}
$file | Out-File $path
Powershell勉強中なんだけどこんな感じ? 正直今のところ頂いた回答の中では>>658さんの回答が模範解答でした。 >>698
良いんだけど、>>658は>>681で言う三番目で、希望は一番目らしいから、あと一工夫だね
正直もう飽きたから他の人がんばって >>697でいいやん
自分の趣味じゃないから読みにくいけど、条件は満たしてる PSはマルチスレッド気軽に使えないの?
ググるとリモート、マルチプロセスとRunspaceのサンプルばっかり出てくるんだが
2.0だとTaskも無いからキビシイのかね >>702
つかえるんじゃない?
どんな処理をしたいということなの。 いやーなんかねHttpListenerのBeginGetContextでクラッシュするんです
マルチスレッド対応してないのかなと マルチスレッドというより(マルチスレッドだけど)
それが非同期に対応しているかという話ね。 原因わかった
別スレッドだとrunspaceが無いからpowershellコードが動かんのだとさ こんな記事あるけど使える?
RunspacePoolを使って、PowerShellを非同期実行
https://www.gmo.jp/report/single/?art_id=195 >>707
今日はそれを調べてた
GetContext使ってメインスレッドで同期的にコンテキストを受けて
ルーティング処理〜レスポンス閉じるまでをrunspaceでOneWay非同期処理するといい感じで動作してるっぽい >>279
こいつアホすぎてムカつく
わからんなら黙ってろかす! TrustedInstallerのままなのはOS不具合かな
最近こういうの放置でアップグレードしてくから困る 聞いてくれやおじさん
UIautomationとやらを探して2日たらし回しにされた
psのgui自動化ツールはこれでええのか 確かに探すの難しくなってるな
UI Automation PowerShell ExtensionsのDownload(再配布)
ttps://www.code-lab.net/?page_id=21648 UIautomationって旧来技術ってことでWin10では
あらたなことは行わないんじゃないのかな。
たしかGUIがWPFだよね。 ISE
VSCode
Visual Studio 2017
でPowerShell開発やってみたけど一番快適にDebugできるのはVSCodeだった 実行ポリシーを変更をBypassに変更してるんだが
.ps1ファイルを実行しようとすると1日1回くらい(その日の最初?)は以下の文章が出る
出なくする方法ありますか?
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "N"):
ちなみにGet-ExecutionPolicyすると
ちゃんとBypassと表示される コンテキストメニューから実行してるなら、関連付け設定が
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
になってるから、Set-ExecutionPolicy -Scope Process Bypass を実行するところでそれが出るんだと思う
関連付け設定を変えれば出てこなくなるよ ありがとう
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "%1"に変えてみた
ついでにダブルクリックだけで実行できるように変えたら便利になった csvの中に時間とデータの2列あって、それの直線近似した切片を取りたいんだけどアルゴリズム組まないとだめ?
なおエクセルは入ってないパソコンで使いたい。 pythonでpandas+leastsquare >>720
単に公式に当てはめればいい
$data = import-csv "csvのパス" -Header X,Y
$meanX = $data.X | measure -Average | select -expand Average
$meanY = $data.Y | measure -Average | select -expand Average
$sd = $data | foreach { ($_.X - $meanX) * ($_.X - $meanX) } | measure -Average | select -expand Average
$cd = $data | foreach { ($_.X - $meanX) * ($_.Y - $meanY) } | measure -Average | select -expand Average
$slope = $cd / $sd
$meanY - $slope * $meanX >>720
Accord.Net使えばいいよ
それか今ならML.NETが良いのかね? >>722
ありがとうございます。簡潔に書かれていてすごい。
>>721
pythonでも出来るのですが、エクセル含めソフトインストールできないPCでの運用なので ■ このスレッドは過去ログ倉庫に格納されています