文字列操作コマンド:文字列の挿入
なかなか面白そうなコマンドですね。 具体的な仕様はどのようにしましょうか? 例を提示してもらえれば、参考にします。
yutakapon への返信
なかなか面白そうなコマンドですね。 具体的な仕様はどのようにしましょうか? 例を提示してもらえれば、参考にします。
ご興味を持って頂きありがとうございます! 仕様ですが、strconcatと同じく、ターゲットの文字列型変数をはじめに記述するコマンド書式ではどうでしょうか?
--- strinsert 文字列を挿入する。
形式
strinsert <strvar> <pos> <string>
解説
文字列変数 <strvar> の <pos> 文字目の直前に文字列 <string> を挿入する。
例 ; varstrの10文字目の直前にバージョン番号を挿入する。 varstr='Tera Term is released.' strinsert varstr 10 ' 4.67'
●実装ついでに、削除の機能もあると面白いです。 strdelete 文字列を削除する。
形式
strdelete <strvar> <pos> <len>
解説
文字列変数 <strvar> の <pos> 文字目から <len> 文字分を削除し詰める。
例 ; varstrの4文字目から3文字を削除し詰める。 varstr='abcdefghi' strdelete varstr 4 3
ku9292 への返信
仕様ですが、strconcatと同じく、ターゲットの文字列型変数をはじめに記述するコマンド書式ではどうでしょうか? --- strinsert 文字列を挿入する。 形式 strinsert <strvar> <pos> <string> 解説 文字列変数 <strvar> の <pos> 文字目の直前に文字列 <string> を挿入する。
「文字目」のオリジンはどうなりますか? 0 or 1? また、文字目が1オリジンだった場合、「1文字目」が指定されたり、<strvar>の 最後の文字目が指定された場合は、どういう扱いになるでしょうか?
例 ; varstrの10文字目の直前にバージョン番号を挿入する。 varstr='Tera Term is released.' strinsert varstr 10 ' 4.67'
この例では、varstrの結果は以下になることが期待値ですか?
'Tera Term4.67 is released.'
●実装ついでに、削除の機能もあると面白いです。 strdelete 文字列を削除する。 形式 strdelete <strvar> <pos> <len> 解説 文字列変数 <strvar> の <pos> 文字目から <len> 文字分を削除し詰める。 例 ; varstrの4文字目から3文字を削除し詰める。 varstr='abcdefghi' strdelete varstr 4 3
この場合の期待値を教えてください。
strvar の長さを超える値、あるいはマイナスの値が pos に指定されたらどうなりますか?
>「文字目」のオリジンはどうなりますか? 0 or 1? また、文字目が1オリジンだった場合、「1文字目」が指定されたり、<strvar>の最後の文字目が指定された場合は、どういう扱いになるでしょうか?
strvarの先頭の文字を1文字目として数えることを想定していました。
varstr='Tera Term is released.'
varstrの10文字目は空白なので、10文字目の直前(9文字目=mの直後)に' 4.67'を挿入するので、元々10文字目だった空白は、' 4.67'の後に順送りに移動されて、
'Tera Term 4.67 is released.'
となることを期待していました。
また、<pos>で1文字目が指定された場合には、strvarの1文字目の直前に挿入されるので、strvarには先頭から挿入された文字が入り、続いて元々の文字が続きます。
●しかし、これだとstrconcatと同じ機能、つまり、<strvar>の最後の文字目の後に挿入(追加)することができないですね。この場合は考えていませんでした。浅はかでした。
そこで、<pos>は文字目の後として扱い、strvarの先頭の文字は1とする。先頭の文字の前に挿入する場合は便宜上0を指定する。末尾の後に追加するときは、最後の文字目を指定する。文字列の中間では、たとえば、'12345'の2文字目に'abc'を挿入すると、'12abc345'になるとすると、うまくいくでしょうか?
削除は、strvarの先頭の文字を1として、指定した文字数を削除し詰めるというのではだめでしょうか?(挿入とは整合性がなくなりますが)
'12345'の先頭から2文字削除 pos=1 len=2 →345
'12345'の3文字目から3文字削除 pos=3 len=3 →12
# ともかくも、実装しやすい方法で構いませんので、、、 宜しくお願い致します。
None への返信
strvar の長さを超える値、あるいはマイナスの値が pos に指定されたらどうなりますか?
想定していませんでした。
strcopyで調べてみると、
・posがマイナスだと、1と解釈される
・posがstrvarの長さを超えると、処理されない
・lenがマイナスだと、処理されない
・lenがstrvarの長さを超えると、strvarの長さの範囲で処理される
となっているので、同様に、
・posがマイナスだと、0と解釈される(先頭に挿入)
・posがstrvarの長さを超えると、処理されない
ということではどうでしょうか?
宜しくお願い致します。
None への返信
None への返信
strvar の長さを超える値、あるいはマイナスの値が pos に指定されたらどうなりますか?
想定していませんでした。 strcopyで調べてみると、 ・posがマイナスだと、1と解釈される ・posがstrvarの長さを超えると、処理されない ・lenがマイナスだと、処理されない ・lenがstrvarの長さを超えると、strvarの長さの範囲で処理される となっているので、同様に、 ・posがマイナスだと、0と解釈される(先頭に挿入) ・posがstrvarの長さを超えると、処理されない ということではどうでしょうか? 宜しくお願い致します。
2010-08-09 23:20 更新者: Noneは、私が更新しました。
以下のような仕様でいかがでしょうか?
--- strinsert 文字列を挿入する。 形式 strinsert <strvar> <index> <string> 解説 文字列変数 <strvar> の <index> 位置(0オリジン)に、文字列 <string> を挿入する。 例 ; strinsert 'abc' 2 'XYZ' -> 'abXYZc' strinsert 'abc' 0 'XYZ' -> 'XYZabc' strinsert 'abc' -1 'XYZ' -> シンタックスエラー strinsert 'abc' 3 'XYZ' -> 'abcXYZ' strinsert 'abc' 4 'XYZ' -> シンタックスエラー
形式 strremove <strvar> <index> <len> 解説 文字列変数 <strvar> の <index> 位置(0オリジン)から <len> 文字分を削除し詰める。 例 ; strremove '123abc456' 3 3 -> '123456' strremove '123abc456' 0 3 -> 'abc456' strremove '123abc456' -1 3 -> シンタックスエラー strremove '123abc456' 8 1 -> '123abc45' strremove '123abc456' 8 2 -> シンタックスエラー strremove '123abc456' 9 1 -> シンタックスエラー strremove '123abc456' 3 0 -> シンタックスエラー
strscan や strmatch では 1 オリジンなのですが、それにあわせたほうがよくないですか?
では、以下のようにしましょうか。
--- strinsert 文字列を挿入する。 形式 strinsert <strvar> <index> <string> 解説 文字列変数 <strvar> の <index> 位置(1オリジン)に、文字列 <string> を挿入する。 例 ; strinsert 'abc' 3 'XYZ' -> 'abXYZc' strinsert 'abc' 1 'XYZ' -> 'XYZabc' strinsert 'abc' -1 'XYZ' -> シンタックスエラー strinsert 'abc' 0 'XYZ' -> シンタックスエラー strinsert 'abc' 4 'XYZ' -> 'abcXYZ' strinsert 'abc' 5 'XYZ' -> シンタックスエラー 形式 strremove <strvar> <index> <len> 解説 文字列変数 <strvar> の <index> 位置(1オリジン)から <len> 文字分を削除し詰める。 例 ; strremove '123abc456' 4 3 -> '123456' strremove '123abc456' 1 3 -> 'abc456' strremove '123abc456' -1 3 -> シンタックスエラー strremove '123abc456' 0 3 -> シンタックスエラー strremove '123abc456' 9 1 -> '123abc45' strremove '123abc456' 9 2 -> シンタックスエラー strremove '123abc456' 10 1 -> シンタックスエラー strremove '123abc456' 4 0 -> シンタックスエラー
1オリジンにすると、統一性があっていいですね!
そもそも、<index>位置に挿入するという扱いだと、1オリジンで良かったのでした。 既存の文字の「前か後か」という感覚に拘泥していました。。。 混乱させてすみません。>yutakapon様
宜しくお願い致します。
ku9292 への返信
1オリジンにすると、統一性があっていいですね! そもそも、<index>位置に挿入するという扱いだと、1オリジンで良かったのでした。 既存の文字の「前か後か」という感覚に拘泥していました。。。 混乱させてすみません。>yutakapon様
早速ですが、strinsertとstrremoveを実装してみました。評価願います。 時間がなかったので、まだドキュメントはありません。
http://ttssh2.sourceforge.jp/snapshot/snapshot-20100811.zip
一応、以下のサンプルコードで確認はしました。
s = '123abc456' strremove s 4 3 ;-> '123456' messagebox s s s = '123abc456' strremove s 1 3 ;-> 'abc456' messagebox s s s = '123abc456' strremove s -1 3 ;-> シンタックスエラー messagebox s s s = '123abc456' strremove s 0 3 ;-> シンタックスエラー messagebox s s s = '123abc456' strremove s 9 1 ;-> '123abc45' messagebox s s s = '123abc456' strremove s 9 2 ;-> シンタックスエラー messagebox s s s = '123abc456' strremove s 10 1 ;-> シンタックスエラー messagebox s s s = '123abc456' strremove s 4 0 ;-> シンタックスエラー messagebox s s end s='abc' strinsert s 3 'XYZ' ;-> 'abXYZc' messagebox s s s='abc' strinsert s 1 'XYZ' ;-> 'XYZabc' messagebox s s s='abc' strinsert s -1 'XYZ' ;-> シンタックスエラー messagebox s s s='abc' strinsert s 0 'XYZ' ;-> シンタックスエラー messagebox s s s='abc' strinsert s 4 'XYZ' ;-> 'abcXYZ' messagebox s s s='abc' strinsert s 5 'XYZ' ;-> シンタックスエラー messagebox s s
yutakapon への返信
早速ですが、strinsertとstrremoveを実装してみました。評価願います。
時間がなかったので、まだドキュメントはありません。
一応、以下のサンプルコードで確認はしました。
早速の実装をありがとうございます。
早速、こちらでもサンプルコードと本来やりたかった処理でも試してみました。
大丈夫でした。(無論ですね!)
# 本来やりたかった処理とは、たとえば、数字を含む文字列を正規表現で合致させて、
# 頭に0を補って数字の桁数を統一したり、頭の0を削除したりという処理です。
# これらをすっきりマクロで記述することができるようになり助かりました。
ku9292 への返信
早速の実装をありがとうございます。 早速、こちらでもサンプルコードと本来やりたかった処理でも試してみました。 大丈夫でした。(無論ですね!)
早速の評価ありがとうございます。ドキュメントも記載しておきます。
余力があれば、.NET FrameworkのStringメソッドにあるような機能をさらにサポートしてみたいと 思ってます。何かご希望はありますか?
http://msdn.microsoft.com/ja-jp/library/7wtc81z6%28v=VS.80%29.aspx
yutakapon への返信
早速の評価ありがとうございます。ドキュメントも記載しておきます。 余力があれば、.NET FrameworkのStringメソッドにあるような機能をさらにサポートしてみたいと 思ってます。何かご希望はありますか? http://msdn.microsoft.com/ja-jp/library/7wtc81z6%28v=VS.80%29.aspx
そうですね~、まずはReplaceメソッドがほしいです。
これが実装されると、正規表現で合致させて、挿入、削除、そして“置換”ができるのでとても嬉しいです。
宜しくお願い致します。
ku9292 への返信
そうですね~、まずはReplaceメソッドがほしいです。 これが実装されると、正規表現で合致させて、挿入、削除、そして“置換”ができるのでとても嬉しいです。
strreplaceコマンドを実装してみました。
http://ttssh2.sourceforge.jp/snapshot/snapshot-20100811_2.zip
strmatchと組み合わせた時のサンプルコードは、以下のようになります。 ドキュメントもご覧ください。
src='Microsoft Windows XP [Version 5.1.2600]' strmatch src '(Version \d+.\d+.)\d+' int2str s result messagebox s groupmatchstr1 pos=result ; 23 mstr=groupmatchstr1 ; Version 5.1. strreplace src pos mstr 'Build ' if result=1 then messagebox src 'result' ; Microsoft Windows XP [Build 2600] endif
yutakapon への返信
strreplaceコマンドを実装してみました。
http://ttssh2.sourceforge.jp/snapshot/snapshot-20100811_2.zip
strmatchと組み合わせた時のサンプルコードは、以下のようになります。
ドキュメントもご覧ください。
早速、strreplaceを動かしてみました。ばっちりです! また、HELPドキュメントも拝見しました。 これで、いままで、無理くり書いていた部分のコードが、 とても簡潔に書き直せます。 どうもありがとうございました。
ku9292 への返信
早速、strreplaceを動かしてみました。ばっちりです! また、HELPドキュメントも拝見しました。 これで、いままで、無理くり書いていた部分のコードが、 とても簡潔に書き直せます。
確認していただき、ありがとうございます。
他にも文字列操作系でほしい機能はありますか? 次のリリースに向け、内部の締めが 8/23 なので、それまでで対応できる ものならば、サポートを検討します。
yutakapon への返信
他にも文字列操作系でほしい機能はありますか?
次のリリースに向け、内部の締めが 8/23 なので、それまでで対応できる
ものならば、サポートを検討します。
はい。文字列操作系の機能は、当分使いそうもないものまであったりすると、いつかは便利になることがあるのでしょうが。。。
まず、自分で使いそうなところとしては、String.Trimでしょうか。
あと、String.SpritとString.Joinもあれば(とても)便利だと思います。teratermマクロでは配列が使えないので、代替として予約変数1~9で対応することになりましょうか?
ku9292 への返信
早速、strreplaceを動かしてみました。ばっちりです! また、HELPドキュメントも拝見しました。 これで、いままで、無理くり書いていた部分のコードが、 とても簡潔に書き直せます。
そもそも、strreplace で正規表現が指定できるようにすれば、よいのでした。 ということで、以下のアーカイブで正規表現に対応させてみました。 使ってみてください。
http://ttssh2.sourceforge.jp/snapshot/snapshot-20100814.zip
ドキュメント: http://ttssh2.sourceforge.jp/manual/ja/macro/command/strreplace.html
None への返信
まず、自分で使いそうなところとしては、String.Trimでしょうか。
書式としては、こんな感じでしょうか?
あと、String.SpritとString.Joinもあれば(とても)便利だと思います。teratermマクロでは配列が使えないので、代替として予約変数1~9で対応することになりましょうか?
そうですね。「配列」そのもののサポート要望は、以前から出てはいるのですが、まだ実装までは 至っていないです。 予約変数1~9で対応するとした場合、どのような書式になるでしょうか?
yutakapon への返信
そもそも、strreplace で正規表現が指定できるようにすれば、よいのでした。 ということで、以下のアーカイブで正規表現に対応させてみました。 使ってみてください。
仕様拡張をありがとうございます。これで元々期待していた機能が実装されたことになります。ちょっと使い込んでみますね!
yutakapon への返信
書式としては、こんな感じでしょうか?
strtrim <strvar> <trimchars>
はい。これでよろしいと思います。
そうですね。「配列」そのもののサポート要望は、以前から出てはいるのですが、まだ実装までは
至っていないです。
予約変数1~9で対応するとした場合、どのような書式になるでしょうか?
予約変数はparam1~param9を使うとして、一案としてこのような感じになりましょうか。
strsplit
文字列から部分文字列を取り出す
形式
strsplit <strvar> <splitter> <intvar>
解説
文字列 <strvar> から区切り記号 <splitter> で区切られた部分文字列を取り出してparam1~param9に返す。
<intvar> には、取得する部分文字列の最大数(9以下)を指定する。
文字列中の部分文字列の数が <intvar> 未満であるとき、部分文字列が代入されなかったparamには、
NULLが代入される。
strsplit "Sun,Mon,Tue,Wed,Thu,Fri,Sat" "," 7
messagebox param1 "parm1"
messagebox param2 "parm2"
messagebox param3 "parm3"
messagebox param4 "parm4"
messagebox param5 "parm5"
messagebox param6 "parm6"
messagebox param7 "parm7"
strjoin
部分文字列を連結し文字列にする
形式
strjoin <strvar> <splitter> <intvar>
解説
param1~param9の部分文字列を区切り記号 <splitter>で連結し文字列 <strvar> を返す。
<intvar> には、連結するparamの数(9以下)を指定する。
param1="Jan"
param2="Feb"
param3="Mar"
param4="Apr"
param5="May"
param6="Jun"
strjoin strvar "," 6
messagebox strvar "strvar"
よろしくお願い致します。
ku9292 への返信
書式としては、こんな感じでしょうか?
strtrim <strvar> <trimchars>
はい。これでよろしいと思います。
早速作ってみました。何か問題あれば、連絡願います。
ku9292 への返信
strsplit 文字列から部分文字列を取り出す 形式 strsplit <strvar> <splitter> <intvar> 解説 文字列 <strvar> から区切り記号 <splitter> で区切られた部分文字列を取り出してparam1~param9に返す。 <intvar> には、取得する部分文字列の最大数(9以下)を指定する。 文字列中の部分文字列の数が <intvar> 未満であるとき、部分文字列が代入されなかったparamには、 NULLが代入される。
strsplit を実装しました。 "param1"は予約済み変数であり、ユーザからは使えないようですので、代わりに"groupmatchstr"を 使うようにしました。
http://ttssh2.sourceforge.jp/snapshot/snapshot-20100816.zip http://ttssh2.sourceforge.jp/manual/ja/macro/command/strsplit.html
yutakapon への返信
strsplit を実装しました。
"param1"は予約済み変数であり、ユーザからは使えないようですので、代わりに"groupmatchstr"を
使うようにしました。
早速の実装をありがとうございます。
src='Sun,Mon,TueThu,Fri,Sat'
strsplit src ',' 7
のように、separatorで区切られた部分文字列がNULLの場合には、
該当する順番のgroupmatchstrNには、次の部分文字列が前詰めされて代入されます。
この事例ではgroupmatchstr4にはThuが代入されます。
CSVファイルの処理等、部分文字列の順番が意味を持つときには、
該当するgroupmatchstrNにはNULLが代入されるほうが都合が良いと思いますが、
如何でしょうか?
yutakapon への返信
早速作ってみました。何か問題あれば、連絡願います。
ありがとうございます。
先頭、末尾にタブ又は空白が含まれそれを削除したい場合には、
エディタでtrimcharsにタブ又は空白を代入しておけば正常に処理されますが、
実装して頂いたstrsplitと同様にspecialとの併用で、
trimchars="\t "
と記述できるように拡張すると、より便利だと思うのですが。
よろしくお願い致します。
ku9292 への返信
src='Sun,Mon,TueThu,Fri,Sat' strsplit src ',' 7 のように、separatorで区切られた部分文字列がNULLの場合には、 該当する順番のgroupmatchstrNには、次の部分文字列が前詰めされて代入されます。 この事例ではgroupmatchstr4にはThuが代入されます。
調査の結果、strtok_s()の仕様でした。 実装を工夫すれば、途中に、区切り文字が連続した場合でも対処できそうです。 ところが、これも strtok_s()の仕様なのですが、先頭に区切り文字が来ると、無視されてしまいます。 これはどうなるのが期待値ですか?
,Sun,Mon,Tue,Thu,Fri,Sat,
yutakapon への返信
これはどうなるのが期待値ですか?
,Sun,Mon,Tue,Thu,Fri,Sat,
僕の個人的な想いとしては、
groupmatchstr1=""
groupmatchstr2=""
groupmatchstr3=""
groupmatchstr4="Sun"
groupmatchstr5="Mon"
groupmatchstr6="Tue"
groupmatchstr7=""
groupmatchstr8=""
groupmatchstr9="Thu"
と、上の行を1レコードにしたCSVファイルを作り、それを普通にExcelで読み込んだときの動作を期待しています。
補足)
groupmatchstrの数は、現状9が上限ですが、部分文字列が多い行をマクロで処理しようとすると不足するかもですね。
文字列の文字数の上限が255文字なので、そう多くの数は必要ないと思われますが、9個は微妙なところかも知れません。
ku9292 への返信
strsplitとstrtimを改修し、snapshot-20100816_2.zip でアップロードしました。 strsplitでは、連続した区切り文字を1つずつ区別するようにしましたが、代わりに 区切り文字には1つのみしか指定できないようになっています。
splitのサポートは延期できませんか?
延び延びになっていますが、配列をサポートしてからそれを使った方が使いやすくなると思います。
doda への返信
splitのサポートは延期できませんか? 延び延びになっていますが、配列をサポートしてからそれを使った方が使いやすくなると思います。
ku9292さん、いかがしましょうか? 配列サポートまで strsplit は封印するか、4.67で現状の仕様でとりあえずサポートしておくか。 8/23までにお返事下さい。
yutakapon への返信
doda への返信
splitのサポートは延期できませんか? 延び延びになっていますが、配列をサポートしてからそれを使った方が使いやすくなると思います。
ku9292さん、いかがしましょうか? 配列サポートまで strsplit は封印するか、4.67で現状の仕様でとりあえずサポートしておくか。 8/23までにお返事下さい。
お世話様です。
僕も、配列のサポート(まずは整数型で)を心待ちにしている一人ですが、
とりあえず、strsplitについては、「現状の仕様のまま」で4.67で実装して頂けると、
通常やりたいことのほとんどに対応可能なのでとても助かります。
# いま可能になったことを手放したくないので。。。
同様の仕様でstrjoinもペアで実装されると、CSVファイル生成が少し楽になるので素敵です。
どうぞよろしくお願い致します。
None への返信
yutakapon への返信
doda への返信
splitのサポートは延期できませんか? 延び延びになっていますが、配列をサポートしてからそれを使った方が使いやすくなると思います。
ku9292さん、いかがしましょうか? 配列サポートまで strsplit は封印するか、4.67で現状の仕様でとりあえずサポートしておくか。
とりあえず、strsplitについては、「現状の仕様のまま」で4.67で実装して頂けると、 通常やりたいことのほとんどに対応可能なのでとても助かります。 # いま可能になったことを手放したくないので。。。
将来的に配列版を作ったときに、strsplit の仕様変更をするか(互換性がなくなる)、別名マクロとする(sprintf/sprintf2のように同じ目的のものが2つになる)ということになります。
前者を取りたいところですが、だれかが現状版で書いたマクロはすべて書き直しを強制することになるので、そう簡単にできません。
一案として、ドキュメントには載せず隠しコマンドにしておくというのも不可能ではないと思いますが、よくないでしょうか?>開発メンバ
maya への返信
None への返信
yutakapon への返信
doda への返信
splitのサポートは延期できませんか? 延び延びになっていますが、配列をサポートしてからそれを使った方が使いやすくなると思います。
ku9292さん、いかがしましょうか? 配列サポートまで strsplit は封印するか、4.67で現状の仕様でとりあえずサポートしておくか。
とりあえず、strsplitについては、「現状の仕様のまま」で4.67で実装して頂けると、 通常やりたいことのほとんどに対応可能なのでとても助かります。 # いま可能になったことを手放したくないので。。。
将来的に配列版を作ったときに、strsplit の仕様変更をするか(互換性がなくなる)、別名マクロとする(sprintf/sprintf2のように同じ目的のものが2つになる)ということになります。 前者を取りたいところですが、だれかが現状版で書いたマクロはすべて書き直しを強制することになるので、そう簡単にできません。 一案として、ドキュメントには載せず隠しコマンドにしておくというのも不可能ではないと思いますが、よくないでしょうか?>開発メンバ
横から失礼します。(さきほどのコメントはログインし忘れ、すみません)
コマンド書式が美しくなくなるかも知れませんが、
strsplit src ',' 9 substr[]
のように、最後に文字列型配列を指定するようにしておいて、
①文字列型配列が指定されていれば、そこに部分文字列を返す。
②部分文字列の数が9以下の場合には、文字型配列と共に、予約変数groupmatchstrNにも値を返す。
→文字列型配列の指定があっても無くても、予約変数groupmatchstrNには値を返す。
ようにしておくと、いま仮に実装して頂いた仕様と整合性が取れたりしないでしょうか?
隠しコマンドというのも、知っていれば使いたかった方々には残念なことでしょうから。
よろしくお願い致します。
yutakapon への返信
ku9292 への返信 strsplitとstrtimを改修し、snapshot-20100816_2.zip でアップロードしました。 strsplitでは、連続した区切り文字を1つずつ区別するようにしましたが、代わりに 区切り文字には1つのみしか指定できないようになっています。
strtrimの動作を、snapshot-20100816_2を使って調べていましたが、削除文字を空白(1文字)にした場合に、処理対象の文字列が、
①先頭が、TAB 空白 文字列 のパターン
②末尾が、文字列 空白 TAB のパターン
であると、該当する先頭又は末尾の空白が削除されないようです。
逆の順序で、先頭が、空白 TAB 文字列 のパターンや、末尾が、TAB 空白 文字列 のパターンでは大丈夫です。
ちょっと見て頂けますでしょうか?よろしくお願い致します。
;src=#09" ""#include" ; NG。先頭の空白が削除されず
;src=" "#09"#include" ; OK
src="#include"" "#09 ; NG。末尾の空白が削除されず
;src="#include"#09" " ; OK
trimchars=" " ; 削除文字は空白
strtrim src trimchars
strlen src
sprintf "len=%d" result
messagebox src inputstr ; '#include '
ku9292 への返信
yutakapon への返信
ku9292 への返信 strsplitとstrtimを改修し、snapshot-20100816_2.zip でアップロードしました。 strsplitでは、連続した区切り文字を1つずつ区別するようにしましたが、代わりに 区切り文字には1つのみしか指定できないようになっています。
strtrimの動作を、snapshot-20100816_2を使って調べていましたが、削除文字を空白(1文字)にした場合に、処理対象の文字列が、 ①先頭が、TAB 空白 文字列 のパターン ②末尾が、文字列 空白 TAB のパターン であると、該当する先頭又は末尾の空白が削除されないようです。 逆の順序で、先頭が、空白 TAB 文字列 のパターンや、末尾が、TAB 空白 文字列 のパターンでは大丈夫です。 ちょっと見て頂けますでしょうか?よろしくお願い致します。 ;src=#09" ""#include" ; NG。先頭の空白が削除されず ;src=" "#09"#include" ; OK src="#include"" "#09 ; NG。末尾の空白が削除されず ;src="#include"#09" " ; OK trimchars=" " ; 削除文字は空白 strtrim src trimchars strlen src sprintf "len=%d" result messagebox src inputstr ; '#include '
自己フォローです。
混乱していました。
①先頭が、TAB 空白 文字列 のパターン
②末尾が、文字列 空白 TAB のパターン
だと、先頭又は末尾の文字はTABなので、空白は削除されなくて当然でした。
申し訳ありません。。。
strsplit ですが、<count> が効いていないようです。
ドキュメントにある3つの例うち最初の1つは、こうなるのが期待値だと思われますがどうでしょうか。
src=',,Sun,Mon,Tue,,Thu,Fri,Sat' strsplit src ',' 7 messagebox groupmatchstr1 "groupmatchstr1" ; '' messagebox groupmatchstr2 "groupmatchstr2" ; '' messagebox groupmatchstr3 "groupmatchstr3" ; 'Sun' messagebox groupmatchstr4 "groupmatchstr4" ; 'Mon' messagebox groupmatchstr5 "groupmatchstr5" ; 'Tue' messagebox groupmatchstr6 "groupmatchstr6" ; '' messagebox groupmatchstr7 "groupmatchstr7" ; 'Thu,Fri,Sat' messagebox groupmatchstr8 "groupmatchstr8" ; '' messagebox groupmatchstr9 "groupmatchstr9" ; ''
ku9292 への返信
strsplit src ',' 9 substr[]
strsplit <strvar> <separator> <count> [<special> [<matches>]] ; matches ... string array
これなら互換性が保てそうですね。
maya への返信
strsplit ですが、<count> が効いていないようです。 ドキュメントにある3つの例うち最初の1つは、こうなるのが期待値だと思われますがどうでしょうか。 {{{ src='Sun,Mon,TueThu,Fri,Sat' strsplit src ',' 7 messagebox groupmatchstr1 "groupmatchstr1" ; messagebox groupmatchstr2 "groupmatchstr2" ; messagebox groupmatchstr3 "groupmatchstr3" ; 'Sun' messagebox groupmatchstr4 "groupmatchstr4" ; 'Mon' messagebox groupmatchstr5 "groupmatchstr5" ; 'Tue' messagebox groupmatchstr6 "groupmatchstr6" ; messagebox groupmatchstr7 "groupmatchstr7" ; 'Thu,Fri,Sat' messagebox groupmatchstr8 "groupmatchstr8" ; messagebox groupmatchstr9 "groupmatchstr9" ; }}}
<count>についてはちゃんと見ていませんでした。 str.splitの動作からすれば、ご指摘の動作が適切だと思います。
上の例で、count=7のときにgroupmatchstr7に"Thu,Fri,Sat"と、残りの文字列の全てを返すようにしておけば、src=groupmatchstry7として再度strsplitを呼ぶと残りの部分文字列も分解できるので、groupmatchstrが9個でも、あまり不自由しないかも知れません。
宜しくお願い致します。
<count>の件は修正しました。 しかし、最後に残った文字列を含めるのは、ちょっと実装上難しいです。
ku9292 への返信
strjoin 部分文字列を連結し文字列にする 形式 strjoin <strvar> <splitter> <intvar>
strjoin、実装しました。
snapshot-20100819.zip
str_replace ですが、現状では最初のマッチ箇所のみ置換しています。
String.Replace や PHP の str_replace はマッチする部分が複数あった場合にすべてを置換します。
perl の =~ s/pattern/replacement/ だと 末尾に g をつけて s/pattern/replacement/g としないとすべてを置換することはしません。
どちらの実装にするかの仕様決定と、ドキュメントへの明記が必要だと思います。
strreplace では正規表現が利用できますが、グループ化された文字列を newstr に指定したくなりそうですが、実装は難しいですよね。
src='Tera Term 4.66' strreplace src 1 'Tera Term (\d\.\d+)' 'ver $1' messagebox src 'result' ; ver 4.66
# これを考えるのが面倒そうだなと思って、フォーラムであのように書きました。
yutakapon への返信
ku9292 への返信
strjoin 部分文字列を連結し文字列にする 形式 strjoin <strvar> <splitter> <intvar>
strjoin、実装しました。 snapshot-20100819.zip
strjoinの実装を有難うございました。早速、動かしてみました。
ところで、HELPドキュメントの解説のところの、
文字列中の部分文字列の数が <count> 以上であるとき、部分文字列が代入されなかったgroupmatchstrには、NULLが代入される。
の部分は、strsplitの説明の名残りなので削除でしょうか?
また、groupmatchstrNは、前の結果が残っているので、<count>指定分は、必ず設定(不要時はクリア)が必要ですね。
ku9292 への返信
strsplit <strvar> <splitter> <intvar>
<intvar> を省略可能に出来ませんでしょうか? 将来的に配列をサポートした時に、
strsplit "a,b,c,d,e..." "," 256 arrayなどと十分に大きな数を指定するというのはあまりやりたくないです。
また配列をサポートする前でも、
strsplit "1,2,3,4,5,6,7,8,9,10..." "," 9 ; groupmatchstr9 => "9,10..." strsplit "1,2,3,4,5,6,7,8,9,10..." "," ; groupmatchstr9 => "9"というように最大数を指定した時と指定しない時で動作を変えると、 用途によって使い分けられるので便利に思います。
ku9292 への返信
実装して頂いたstrsplitと同様にspecialとの併用で、 trimchars="\t " と記述できるように拡張すると、より便利だと思うのですが。
これって、どうしても必要でしょうか? 既存の文法でも、
trimchars = #09" "と書けます。
一部のコマンドのみに通用する文法というのは混乱の元なので、あまりやりたくないです。
# そういう意味では、今回追加した str~ コマンド全般で <sp> のサポートを無くしたいです
あと、strsplit での分割最大数を省略可能にする為にも <sp> はなくしたいです。
strsplit ですが、いくつに分割されたかというのを把握できるようにしたいです。
例えば、result に分割数を入れる事は出来ないでしょうか?
doda への返信
最大数を指定した時と指定しない時で動作を変えると、 用途によって使い分けられるので便利に思います。
count を省略可能にすると「countを省略 + array」が出来なくなりますが、想定内でしょうか。
第三引数の型によって動作を変えるというのも不可能ではありませんが、それはあまりよい仕様ではないように思います。
doda への返信
一部のコマンドのみに通用する文法というのは混乱の元なので、あまりやりたくないです。
# そういう意味では、今回追加した str~ コマンド全般で <sp> のサポートを無くしたいです
あー、これは messagebox, yesnobox, statusbox, inputbox で私が special を入れてしまったせいですね。special な文字列に変換する(RestoreNewLine()を通す)コマンドを作ればよかったのに。
# 今からでもそうしたい…。あと sprintf2 を sprintf に置き換えて一つにしたい…
TO: mayaさん・dodaさん
ちょっと、私のほうは 8/23 まであまり工数が取れない感じなので、 あとはお二人で直接いじってもらって構いません。
doda への返信
ku9292 への返信
これって、どうしても必要でしょうか?
はい。必要性は薄く、ご指摘のtrimchars = #09" "とかの記述で対応できるので問題ありません。
他のマクロコマンドでの実装に合わせてはどうでしょうか?程度の話でした。
一部のコマンドのみに通用する文法というのは混乱の元なので、あまりやりたくないです。
# そういう意味では、今回追加した str~ コマンド全般で <sp> のサポートを無くしたいです
あと、strsplit での分割最大数を省略可能にする為にも <sp> はなくしたいです。
弊害が大きいならば、<sp>は削除して頂いても(私は)構いません。
よろしくお願い致します。
yutakapon への返信
TO: mayaさん・dodaさん ちょっと、私のほうは 8/23 まであまり工数が取れない感じなので、 あとはお二人で直接いじってもらって構いません。
横から失礼します。
strsplitですが、当初<count>の必要性を感じたのは、
①CSVファイルレコードの先頭N項目だけを意識して抽出したい
②代入先の予約変数が9個までなので、それを意識しないとまずそう
というところからです。
部分文字列が9個超あって、9個目以降が予約変数の9番目にすべて格納する仕様にするならば、
<count>を無くしてもよいかも知れません。同時に、<special>も無くして
strsplit <strvar> <separator> <matches> ; matches ... string array
にすれば、後日、文字型配列をサポートしても互換性が保たれるでしょうか?
<strvar>から幾つの部分文字列を抽出したかがresultに返される実装はうれしいです。
その場合に、部分文字列数がぴったり9個ある場合と、部分文字列が9個超ある場合の
識別をどうしましょうか?前者はresult=9が正しいですが、後者は?
よろしくお願い致します。
maya への返信
count を省略可能にすると「countを省略 + array」が出来なくなりますが、想定内でしょうか。
第三引数の型によって動作を変えるというのも不可能ではありませんが、それはあまりよい仕様ではないように思います。
引数の型で動作を変えるのを考えていました。
String.Split もオーバーロードされていて引数の型によって動作が変わるので、あってもいいんじゃないかと思っています。
maya への返信
あー、これは messagebox, yesnobox, statusbox, inputbox で私が special を入れてしまったせいですね。
この時はなぜか気にならなかったんですよね。
special な文字列に変換する(RestoreNewLine()を通す)コマンドを作ればよかったのに。
コマンドも有るといいと思いますが、一々コマンドを通すのも面倒な場合も有ると思うので、 エスケープを認識する文字列リテラルを新設すると便利かなと考えています。
messagebox #"line1\nline2" "title"とか
messagebox `column1\tcolumn2` "title"みたいな感じで。
# 今からでもそうしたい…。あと sprintf2 を sprintf に置き換えて一つにしたい…
自分は、strcopy や getenv などで結果を格納する変数を後ろに指定するのが気になっています。
フォーラムで例を書いた時に、getenv と getdate で逆になっているので違和感を覚えました。
# 変えたいけれど、今更変えられないよなあ
doda への返信
{{{ strsplit "1,2,3,4,5,6,7,8,9,10..." "," 9 ; groupmatchstr9 => "9,10..." strsplit "1,2,3,4,5,6,7,8,9,10..." "," ; groupmatchstr9 => "9" }}} というように最大数を指定した時と指定しない時で動作を変えると、 用途によって使い分けられるので便利に思います。
これだと 9 でなくても両方の動きがほしい、と言われるかもしれませんが、その場合に指定のしようがない気がします。
ひとまず count を optional(default=9) にします。
文字列型変数の指定位置に、文字列を挿入する文字列操作コマンドがあると便利なことがあります。 strlen、strcopy及びstrconcatを駆使すれば良いのですが、作業用変数も必要だったりするので。 宜しくお願い致します。